ref: e6b4528626528c2bf11f760bfc660375195e6055
author: Ori Bernstein <ori@eigenstate.org>
date: Tue Jun 8 19:10:51 EDT 2021
python: archive it
--- /dev/null
+++ b/sys/lib/python/BaseHTTPServer.py
@@ -1,0 +1,578 @@
+"""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()
+import mimetools
+import SocketServer
+
+# Default error message
+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>
+"""
+
+def _quote_html(html):
+ return html.replace("&", "&").replace("<", "<").replace(">", ">")
+
+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__
+
+ 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 = "HTTP/0.9" # Default
+ self.close_connection = 1
+ requestline = self.raw_requestline
+ if requestline[-2:] == '\r\n':
+ requestline = requestline[:-2]
+ elif requestline[-1:] == '\n':
+ requestline = requestline[:-1]
+ 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.
+
+ """
+ self.raw_requestline = self.rfile.readline()
+ 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()
+
+ 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", "text/html")
+ 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
+
+ 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, *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(*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 host and current date/time are prefixed to
+ every message.
+
+ """
+
+ sys.stderr.write("%s - - [%s] %s\n" %
+ (self.address_string(),
+ 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 server.'),
+ 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()
--- /dev/null
+++ b/sys/lib/python/Bastion.py
@@ -1,0 +1,177 @@
+"""Bastionification utility.
+
+A bastion (for another object -- the 'original') is an object that has
+the same methods as the original but does not give access to its
+instance variables. Bastions have a number of uses, but the most
+obvious one is to provide code executing in restricted mode with a
+safe interface to an object implemented in unrestricted mode.
+
+The bastionification routine has an optional second argument which is
+a filter function. Only those methods for which the filter method
+(called with the method name as argument) returns true are accessible.
+The default filter method returns true unless the method name begins
+with an underscore.
+
+There are a number of possible implementations of bastions. We use a
+'lazy' approach where the bastion's __getattr__() discipline does all
+the work for a particular method the first time it is used. This is
+usually fastest, especially if the user doesn't call all available
+methods. The retrieved methods are stored as instance variables of
+the bastion, so the overhead is only occurred on the first use of each
+method.
+
+Detail: the bastion class has a __repr__() discipline which includes
+the repr() of the original object. This is precomputed when the
+bastion is created.
+
+"""
+
+__all__ = ["BastionClass", "Bastion"]
+
+from types import MethodType
+
+
+class BastionClass:
+
+ """Helper class used by the Bastion() function.
+
+ You could subclass this and pass the subclass as the bastionclass
+ argument to the Bastion() function, as long as the constructor has
+ the same signature (a get() function and a name for the object).
+
+ """
+
+ def __init__(self, get, name):
+ """Constructor.
+
+ Arguments:
+
+ get - a function that gets the attribute value (by name)
+ name - a human-readable name for the original object
+ (suggestion: use repr(object))
+
+ """
+ self._get_ = get
+ self._name_ = name
+
+ def __repr__(self):
+ """Return a representation string.
+
+ This includes the name passed in to the constructor, so that
+ if you print the bastion during debugging, at least you have
+ some idea of what it is.
+
+ """
+ return "<Bastion for %s>" % self._name_
+
+ def __getattr__(self, name):
+ """Get an as-yet undefined attribute value.
+
+ This calls the get() function that was passed to the
+ constructor. The result is stored as an instance variable so
+ that the next time the same attribute is requested,
+ __getattr__() won't be invoked.
+
+ If the get() function raises an exception, this is simply
+ passed on -- exceptions are not cached.
+
+ """
+ attribute = self._get_(name)
+ self.__dict__[name] = attribute
+ return attribute
+
+
+def Bastion(object, filter = lambda name: name[:1] != '_',
+ name=None, bastionclass=BastionClass):
+ """Create a bastion for an object, using an optional filter.
+
+ See the Bastion module's documentation for background.
+
+ Arguments:
+
+ object - the original object
+ filter - a predicate that decides whether a function name is OK;
+ by default all names are OK that don't start with '_'
+ name - the name of the object; default repr(object)
+ bastionclass - class used to create the bastion; default BastionClass
+
+ """
+
+ raise RuntimeError, "This code is not secure in Python 2.2 and 2.3"
+
+ # Note: we define *two* ad-hoc functions here, get1 and get2.
+ # Both are intended to be called in the same way: get(name).
+ # It is clear that the real work (getting the attribute
+ # from the object and calling the filter) is done in get1.
+ # Why can't we pass get1 to the bastion? Because the user
+ # would be able to override the filter argument! With get2,
+ # overriding the default argument is no security loophole:
+ # all it does is call it.
+ # Also notice that we can't place the object and filter as
+ # instance variables on the bastion object itself, since
+ # the user has full access to all instance variables!
+
+ def get1(name, object=object, filter=filter):
+ """Internal function for Bastion(). See source comments."""
+ if filter(name):
+ attribute = getattr(object, name)
+ if type(attribute) == MethodType:
+ return attribute
+ raise AttributeError, name
+
+ def get2(name, get1=get1):
+ """Internal function for Bastion(). See source comments."""
+ return get1(name)
+
+ if name is None:
+ name = repr(object)
+ return bastionclass(get2, name)
+
+
+def _test():
+ """Test the Bastion() function."""
+ class Original:
+ def __init__(self):
+ self.sum = 0
+ def add(self, n):
+ self._add(n)
+ def _add(self, n):
+ self.sum = self.sum + n
+ def total(self):
+ return self.sum
+ o = Original()
+ b = Bastion(o)
+ testcode = """if 1:
+ b.add(81)
+ b.add(18)
+ print "b.total() =", b.total()
+ try:
+ print "b.sum =", b.sum,
+ except:
+ print "inaccessible"
+ else:
+ print "accessible"
+ try:
+ print "b._add =", b._add,
+ except:
+ print "inaccessible"
+ else:
+ print "accessible"
+ try:
+ print "b._get_.func_defaults =", map(type, b._get_.func_defaults),
+ except:
+ print "inaccessible"
+ else:
+ print "accessible"
+ \n"""
+ exec testcode
+ print '='*20, "Using rexec:", '='*20
+ import rexec
+ r = rexec.RExec()
+ m = r.add_module('__main__')
+ m.b = b
+ r.r_exec(testcode)
+
+
+if __name__ == '__main__':
+ _test()
--- /dev/null
+++ b/sys/lib/python/CGIHTTPServer.py
@@ -1,0 +1,362 @@
+"""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
+
+
+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.
+
+ Return a tuple (dir, rest) if self.path requires running a
+ CGI script, None if not. Note that rest begins with a
+ slash if it is not empty.
+
+ The default implementation tests whether the path
+ begins with one of the strings in the list
+ self.cgi_directories (and the next character is a '/'
+ or the end of the string).
+
+ """
+
+ path = self.path
+
+ for x in self.cgi_directories:
+ i = len(x)
+ if path[:i] == x and (not path[i:] or path[i] == '/'):
+ self.cgi_info = path[:i], path[i+1:]
+ 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 = {}
+ 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
+ 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'):
+ env.setdefault(k, "")
+ os.environ.update(env)
+
+ 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, os.environ)
+ except:
+ self.server.handle_error(self.request, self.client_address)
+ os._exit(127)
+
+ elif self.have_popen2 or self.have_popen3:
+ # Windows -- use popen2 or popen3 to create a subprocess
+ import shutil
+ if self.have_popen3:
+ popenx = os.popen3
+ else:
+ popenx = os.popen2
+ 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 = "%s -u %s" % (interp, cmdline)
+ if '=' not in query and '"' not in query:
+ cmdline = '%s "%s"' % (cmdline, query)
+ self.log_message("command: %s", cmdline)
+ try:
+ nbytes = int(length)
+ except (TypeError, ValueError):
+ nbytes = 0
+ files = popenx(cmdline, 'b')
+ fi = files[0]
+ fo = files[1]
+ if self.have_popen3:
+ fe = files[2]
+ if self.command.lower() == "post" and nbytes > 0:
+ data = self.rfile.read(nbytes)
+ fi.write(data)
+ # throw away additional data [see bug #427345]
+ while select.select([self.rfile._sock], [], [], 0)[0]:
+ if not self.rfile._sock.recv(1):
+ break
+ fi.close()
+ shutil.copyfileobj(fo, self.wfile)
+ if self.have_popen3:
+ errors = fe.read()
+ fe.close()
+ if errors:
+ self.log_error('%s', errors)
+ sts = fo.close()
+ if sts:
+ self.log_error("CGI script exit status %#x", sts)
+ else:
+ self.log_message("CGI script exited OK")
+
+ else:
+ # Other O.S. -- execute script in this process
+ save_argv = sys.argv
+ save_stdin = sys.stdin
+ save_stdout = sys.stdout
+ save_stderr = sys.stderr
+ try:
+ save_cwd = os.getcwd()
+ try:
+ sys.argv = [scriptfile]
+ if '=' not in decoded_query:
+ sys.argv.append(decoded_query)
+ sys.stdout = self.wfile
+ sys.stdin = self.rfile
+ execfile(scriptfile, {"__name__": "__main__"})
+ finally:
+ sys.argv = save_argv
+ sys.stdin = save_stdin
+ sys.stdout = save_stdout
+ sys.stderr = save_stderr
+ os.chdir(save_cwd)
+ except SystemExit, sts:
+ self.log_error("CGI script exit status %s", str(sts))
+ else:
+ self.log_message("CGI script exited OK")
+
+
+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()
--- /dev/null
+++ b/sys/lib/python/ConfigParser.py
@@ -1,0 +1,640 @@
+"""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
+"""
+
+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 __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
+
+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
+
+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
+
+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
+
+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
+
+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)
+
+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 = []
+
+ 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
+
+
+
+class RawConfigParser:
+ def __init__(self, defaults=None):
+ self._sections = {}
+ self._defaults = {}
+ 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.
+ """
+ if section in self._sections:
+ raise DuplicateSectionError(section)
+ self._sections[section] = {}
+
+ 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 = {}
+ 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):
+ """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__":
+ fp.write("%s = %s\n" %
+ (key, str(value).replace('\n', '\n\t')))
+ 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
+ )
+
+ 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] = "%s\n%s" % (cursect[optname], 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 = {'__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')
+ 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 = ''
+ optname = self.optionxform(optname.rstrip())
+ 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
+
+
+class ConfigParser(RawConfigParser):
+
+ def get(self, section, option, raw=False, vars=None):
+ """Get an option value for a given 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
+ option = self.optionxform(option)
+ try:
+ value = d[option]
+ except KeyError:
+ raise NoOptionError(option, section)
+
+ if raw:
+ 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 "%(" in value:
+ value = self._KEYCRE.sub(self._interpolation_replace, value)
+ try:
+ value = value % vars
+ except KeyError, e:
+ raise InterpolationMissingOptionError(
+ option, section, rawval, e[0])
+ else:
+ break
+ if "%(" 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_match = re.compile(r"%\(([^)]+)\)s").match
+
+ 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_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):
+ """Set an option. Extend ConfigParser.set: check for string values."""
+ if not isinstance(value, basestring):
+ raise TypeError("option values must be strings")
+ ConfigParser.set(self, section, option, value)
--- /dev/null
+++ b/sys/lib/python/Cookie.py
@@ -1,0 +1,746 @@
+#!/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',
+
+ '"' : '\\"', '\\' : '\\\\',
+
+ '\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 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",
+ "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), )
+ # 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]))
+ 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
+ ""+ _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(rawdata)
+ 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:
--- /dev/null
+++ b/sys/lib/python/DocXMLRPCServer.py
@@ -1,0 +1,306 @@
+"""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 expressions 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('"', '"')
+ 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/peps/pep-%04d.html' % 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=None, 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>' % (anchor, 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]
+
+ 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 = methods.items()
+ method_items.sort()
+ 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 self.funcs.has_key(method_name):
+ 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)
+
+ # shut down the connection
+ self.wfile.flush()
+ self.connection.shutdown(1)
+
+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):
+ SimpleXMLRPCServer.__init__(self, addr, requestHandler, logRequests)
+ 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)
+ sys.stdout.write(response)
+
+ def __init__(self):
+ CGIXMLRPCRequestHandler.__init__(self)
+ XMLRPCDocGenerator.__init__(self)
+
+if __name__ == '__main__':
+ def deg_to_rad(deg):
+ """deg_to_rad(90) => 1.5707963267948966
+
+ Converts an angle in degrees to an angle in radians"""
+ import math
+ return deg * math.pi / 180
+
+ server = DocXMLRPCServer(("localhost", 8000))
+
+ server.set_server_title("Math Server")
+ server.set_server_name("Math XML-RPC Server")
+ server.set_server_documentation("""This server supports various mathematical functions.
+
+You can use it from Python as follows:
+
+>>> from xmlrpclib import ServerProxy
+>>> s = ServerProxy("http://localhost:8000")
+>>> s.deg_to_rad(90.0)
+1.5707963267948966""")
+
+ server.register_function(deg_to_rad)
+ server.register_introspection_functions()
+
+ server.serve_forever()
--- /dev/null
+++ b/sys/lib/python/HTMLParser.py
@@ -1,0 +1,369 @@
+"""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('[&<]')
+interesting_cdata = re.compile(r'<(/|\Z)')
+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:_]*')
+attrfind = re.compile(
+ r'\s*([a-zA-Z_][-.:a-zA-Z_0-9]*)(\s*=\s*'
+ r'(\'[^\']*\'|"[^"]*"|[-a-zA-Z0-9./,:;+*%?!&$\(\)_#=~@]*))?')
+
+locatestarttagend = re.compile(r"""
+ <[a-zA-Z][-.a-zA-Z0-9:_]* # tag name
+ (?:\s+ # whitespace before attribute name
+ (?:[a-zA-Z_][-.:a-zA-Z0-9_]* # attribute name
+ (?:\s*=\s* # value indicator
+ (?:'[^']*' # LITA-enclosed value
+ |\"[^\"]*\" # LIT-enclosed value
+ |[^'\">\s]+ # bare value
+ )
+ )?
+ )
+ )*
+ \s* # trailing whitespace
+""", re.VERBOSE)
+endendtag = re.compile('>')
+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
+ markupbase.ParserBase.reset(self)
+
+ def feed(self, data):
+ """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):
+ self.interesting = interesting_cdata
+
+ def clear_cdata_mode(self):
+ self.interesting = interesting_normal
+
+ # 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:
+ 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_declaration(i)
+ elif (i + 1) < n:
+ self.handle_data("<")
+ k = i + 1
+ else:
+ break
+ if k < 0:
+ if end:
+ self.error("EOF in middle of construct")
+ break
+ 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:
+ 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:
+ self.handle_data(rawdata[i:n])
+ i = self.updatepos(i, n)
+ self.rawdata = rawdata[i:]
+
+ # 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 = rawdata[i+1:k].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]
+ 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.error("junk characters in start tag: %r"
+ % (rawdata[k:endpos][:20],))
+ 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()
+ 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
+ self.updatepos(i, j)
+ self.error("malformed start tag")
+ 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
+ j = match.end()
+ match = endtagfind.match(rawdata, i) # </ + tag + >
+ if not match:
+ self.error("bad end tag: %r" % (rawdata[i:j],))
+ tag = match.group(1)
+ self.handle_endtag(tag.lower())
+ self.clear_cdata_mode()
+ return j
+
+ # 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):
+ self.error("unknown declaration: %r" % (data,))
+
+ # Internal -- helper to remove special character quoting
+ def unescape(self, s):
+ if '&' not in s:
+ return s
+ s = s.replace("<", "<")
+ s = s.replace(">", ">")
+ s = s.replace("'", "'")
+ s = s.replace(""", '"')
+ s = s.replace("&", "&") # Must be last
+ return s
--- /dev/null
+++ b/sys/lib/python/MimeWriter.py
@@ -1,0 +1,181 @@
+"""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"]
+
+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
--- /dev/null
+++ b/sys/lib/python/Queue.py
@@ -1,0 +1,215 @@
+"""A multi-producer, multi-consumer queue."""
+
+from time import time as _time
+from collections import deque
+
+__all__ = ['Empty', 'Full', 'Queue']
+
+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):
+ try:
+ import threading
+ except ImportError:
+ import dummy_threading as threading
+ 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.notifyAll()
+ 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 = self._empty()
+ self.mutex.release()
+ return n
+
+ def full(self):
+ """Return True if the queue is full, False otherwise (not reliable!)."""
+ self.mutex.acquire()
+ n = self._full()
+ 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 not block:
+ if self._full():
+ raise Full
+ elif timeout is None:
+ while self._full():
+ self.not_full.wait()
+ else:
+ if timeout < 0:
+ raise ValueError("'timeout' must be a positive number")
+ endtime = _time() + timeout
+ while self._full():
+ 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 self._empty():
+ raise Empty
+ elif timeout is None:
+ while self._empty():
+ self.not_empty.wait()
+ else:
+ if timeout < 0:
+ raise ValueError("'timeout' must be a positive number")
+ endtime = _time() + timeout
+ while self._empty():
+ 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.maxsize = maxsize
+ self.queue = deque()
+
+ def _qsize(self):
+ return len(self.queue)
+
+ # Check whether the queue is empty
+ def _empty(self):
+ return not self.queue
+
+ # Check whether the queue is full
+ def _full(self):
+ return self.maxsize > 0 and len(self.queue) == self.maxsize
+
+ # 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()
--- /dev/null
+++ b/sys/lib/python/SimpleHTTPServer.py
@@ -1,0 +1,218 @@
+"""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 urlparse
+import cgi
+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)
+ if ctype.startswith('text/'):
+ mode = 'r'
+ else:
+ mode = 'rb'
+ try:
+ f = open(path, mode)
+ 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())
+ 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("<title>Directory listing for %s</title>\n" % displaypath)
+ f.write("<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")
+ length = f.tell()
+ f.seek(0)
+ self.send_response(200)
+ self.send_header("Content-type", "text/html")
+ 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 = urlparse.urlparse(path)[2]
+ 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()
--- /dev/null
+++ b/sys/lib/python/SimpleXMLRPCServer.py
@@ -1,0 +1,595 @@
+"""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
+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
+ callable(getattr(obj, member))]
+
+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. There should never be any
+ reason to instantiate this class directly.
+ """
+
+ def __init__(self, allow_none, encoding):
+ 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):
+ """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 prefered 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
+ response = xmlrpclib.dumps(
+ xmlrpclib.Fault(1, "%s:%s" % (sys.exc_type, sys.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 self.funcs.has_key(method_name):
+ 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:
+ results.append(
+ {'faultCode' : 1,
+ 'faultString' : "%s:%s" % (sys.exc_type, sys.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')
+
+ 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)
+ L.append(self.rfile.read(chunk_size))
+ size_remaining -= len(L[-1])
+ data = ''.join(L)
+
+ # 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)
+ )
+ except: # This should only happen if the module is buggy
+ # internal error, report as HTTP server error
+ self.send_response(500)
+ self.end_headers()
+ else:
+ # got a valid XML RPC response
+ self.send_response(200)
+ self.send_header("Content-type", "text/xml")
+ self.send_header("Content-length", str(len(response)))
+ self.end_headers()
+ self.wfile.write(response)
+
+ # shut down the connection
+ self.wfile.flush()
+ self.connection.shutdown(1)
+
+ 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)
+ # shut down the connection
+ self.wfile.flush()
+ self.connection.shutdown(1)
+
+ 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
+
+ def __init__(self, addr, requestHandler=SimpleXMLRPCRequestHandler,
+ logRequests=True, allow_none=False, encoding=None):
+ self.logRequests = logRequests
+
+ SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding)
+ SocketServer.TCPServer.__init__(self, addr, requestHandler)
+
+ # [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 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)
+ 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: text/html'
+ print 'Content-Length: %d' % len(response)
+ 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
+ if request_text is None:
+ request_text = sys.stdin.read()
+
+ 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()
--- /dev/null
+++ b/sys/lib/python/SocketServer.py
@@ -1,0 +1,588 @@
+"""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 sys
+import os
+
+__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()
+ - 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
+ - verify_request(request, client_address)
+ - server_close()
+ - process_request(request, client_address)
+ - 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:
+
+ - address_family
+ - socket_type
+ - allow_reuse_address
+
+ Instance variables:
+
+ - RequestHandlerClass
+ - socket
+
+ """
+
+ def __init__(self, server_address, RequestHandlerClass):
+ """Constructor. May be extended, do not override."""
+ self.server_address = server_address
+ self.RequestHandlerClass = RequestHandlerClass
+
+ def server_activate(self):
+ """Called by constructor to activate the server.
+
+ May be overridden.
+
+ """
+ pass
+
+ def serve_forever(self):
+ """Handle one request at a time until doomsday."""
+ while 1:
+ self.handle_request()
+
+ # The distinction between handling, getting, processing and
+ # finishing a request is fairly arbitrary. Remember:
+ #
+ # - handle_request() is the top-level call. It calls
+ # 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."""
+ 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.close_request(request)
+
+ 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.close_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 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)
+ - serve_forever()
+ - 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
+ - verify_request(request, client_address)
+ - process_request(request, client_address)
+ - 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:
+
+ - 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):
+ """Constructor. May be extended, do not override."""
+ BaseServer.__init__(self, server_address, RequestHandlerClass)
+ self.socket = socket.socket(self.address_family,
+ self.socket_type)
+ 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)
+
+ 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 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 close_request(self, request):
+ # No need to close anything.
+ pass
+
+class ForkingMixIn:
+
+ """Mix-in class to handle each request in a new process."""
+
+ active_children = None
+ max_children = 40
+
+ def collect_children(self):
+ """Internal routine to wait for died children."""
+ while self.active_children:
+ if len(self.active_children) < self.max_children:
+ options = os.WNOHANG
+ else:
+ # If the maximum number of children are already
+ # running, block while waiting for a child to exit
+ options = 0
+ try:
+ pid, status = os.waitpid(0, options)
+ except os.error:
+ pid = None
+ if not pid: break
+ self.active_children.remove(pid)
+
+ 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)
+ return
+ else:
+ # Child process.
+ # This must never return, hence os._exit()!
+ try:
+ self.finish_request(request, client_address)
+ os._exit(0)
+ except:
+ try:
+ self.handle_error(request, client_address)
+ 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.close_request(request)
+ except:
+ self.handle_error(request, client_address)
+ self.close_request(request)
+
+ def process_request(self, request, client_address):
+ """Start a new thread to process the request."""
+ import threading
+ 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
+ try:
+ self.setup()
+ self.handle()
+ self.finish()
+ finally:
+ sys.exc_traceback = None # Help garbage collection
+
+ 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
+
+ def setup(self):
+ self.connection = self.request
+ 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)
--- /dev/null
+++ b/sys/lib/python/StringIO.py
@@ -1,0 +1,323 @@
+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 < 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:
+ 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.
+ """
+ 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()
--- /dev/null
+++ b/sys/lib/python/UserDict.py
@@ -1,0 +1,175 @@
+"""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)
+ 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 self.data.has_key(key)
+ 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 not self.has_key(key):
+ return failobj
+ return self[key]
+ def setdefault(self, key, failobj=None):
+ if not self.has_key(key):
+ 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)
+
+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:
+ value = 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())
--- /dev/null
+++ b/sys/lib/python/UserList.py
@@ -1,0 +1,85 @@
+"""A more or less complete user-defined wrapper around list objects."""
+
+class UserList:
+ 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))
+ 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)
--- /dev/null
+++ b/sys/lib/python/UserString.py
@@ -1,0 +1,194 @@
+#!/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
+
+__all__ = ["UserString","MutableString"]
+
+class UserString:
+ 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):
+ """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=""):
+ self.data = string
+ def __hash__(self):
+ raise TypeError, "unhashable type (it is mutable)"
+ def __setitem__(self, index, sub):
+ 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 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
+
+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())
--- /dev/null
+++ b/sys/lib/python/_LWPCookieJar.py
@@ -1,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))
--- /dev/null
+++ b/sys/lib/python/_MozillaCookieJar.py
@@ -1,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()
--- /dev/null
+++ b/sys/lib/python/__future__.py
@@ -1,0 +1,116 @@
+"""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",
+]
+
+__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
+
+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),
+ (2, 7, 0, "alpha", 0),
+ CO_FUTURE_ABSOLUTE_IMPORT)
+
+with_statement = _Feature((2, 5, 0, "alpha", 1),
+ (2, 6, 0, "alpha", 0),
+ CO_FUTURE_WITH_STATEMENT)
--- /dev/null
+++ b/sys/lib/python/__phello__.foo.py
@@ -1,0 +1,1 @@
+# This file exists as a helper for the test.test_frozen module.
--- /dev/null
+++ b/sys/lib/python/_strptime.py
@@ -1,0 +1,452 @@
+"""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
+
+__author__ = "Brett Cannon"
+__email__ = "brett@python.org"
+
+__all__ = ['strptime']
+
+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])",
+ '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
+ _cache_lock.acquire()
+ try:
+ time_re = _TimeRE_cache
+ locale_time = time_re.locale_time
+ if _getlang() != locale_time.lang:
+ _TimeRE_cache = TimeRE()
+ _regex_cache = {}
+ if len(_regex_cache) > _CACHE_MAX_SIZE:
+ _regex_cache.clear()
+ format_regex = _regex_cache.get(format)
+ if not format_regex:
+ try:
+ format_regex = time_re.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
+ finally:
+ _cache_lock.release()
+ found = format_regex.match(data_string)
+ if not found:
+ raise ValueError("time data did not match format: data=%s fmt=%s" %
+ (data_string, format))
+ if len(data_string) != found.end():
+ raise ValueError("unconverted data remains: %s" %
+ data_string[found.end():])
+ year = 1900
+ month = day = 1
+ hour = minute = second = 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 == '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
+ # 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()
+ return time.struct_time((year, month, day,
+ hour, minute, second,
+ weekday, julian, tz))
--- /dev/null
+++ b/sys/lib/python/_threading_local.py
@@ -1,0 +1,241 @@
+"""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__')
+ currentThread().__dict__[key] = dict
+
+ return self
+
+def _patch(self):
+ key = object.__getattribute__(self, '_local__key')
+ d = currentThread().__dict__.get(key)
+ if d is None:
+ d = {}
+ currentThread().__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):
+ lock = object.__getattribute__(self, '_local__lock')
+ lock.acquire()
+ try:
+ _patch(self)
+ return object.__setattr__(self, name, value)
+ finally:
+ lock.release()
+
+ def __delattr__(self, 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:
+ threads = list(threading.enumerate())
+ except:
+ # If enumerate 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 currentThread, RLock
--- /dev/null
+++ b/sys/lib/python/aifc.py
@@ -1,0 +1,961 @@
+"""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
+
+_skiplist = 'COMT', 'INST', 'MIDI', 'AESD', \
+ 'APPL', 'NAME', 'AUTH', '(c) ', 'ANNO'
+
+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_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_long(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(chr(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: # 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_short(f, expon)
+ _write_long(f, himant)
+ _write_long(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 = Chunk(file)
+ if self._file.getname() != 'FORM':
+ raise Error, 'file does not start with FORM id'
+ formdata = self._file.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)
+ elif chunkname in _skiplist:
+ pass
+ else:
+ raise Error, 'unrecognized chunk type '+chunk.chunkname
+ 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 = None
+
+ 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, (nchannels, sampwidth, framerate, nframes, 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.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):
+ 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
+ self._file.flush()
+ self._file = None
+
+ #
+ # 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_long(self._file, 4)
+ _write_long(self._file, self._version)
+ else:
+ self._file.write('AIFF')
+ self._file.write('COMM')
+ _write_long(self._file, commlength)
+ _write_short(self._file, self._nchannels)
+ self._nframes_pos = self._file.tell()
+ _write_long(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_long(self._file, self._datalength + 8)
+ _write_long(self._file, 0)
+ _write_long(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_long(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_long(self._file, self._nframeswritten)
+ self._file.seek(self._ssnd_length_pos, 0)
+ _write_long(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_long(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_long(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."
--- /dev/null
+++ b/sys/lib/python/anydbm.py
@@ -1,0 +1,83 @@
+"""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, add interfaces to other dbm-like
+implementations.
+
+The open function has an optional second argument. This can be 'r',
+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. The default is 'r'.
+
+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.
+
+"""
+
+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):
+ # 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)
--- /dev/null
+++ b/sys/lib/python/asynchat.py
@@ -1,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
--- /dev/null
+++ b/sys/lib/python/asyncore.py
@@ -1,0 +1,551 @@
+# -*- 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 os
+from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, \
+ ENOTCONN, ESHUTDOWN, EINTR, EISCONN, errorcode
+
+try:
+ socket_map
+except NameError:
+ socket_map = {}
+
+class ExitNow(Exception):
+ pass
+
+def read(obj):
+ try:
+ obj.handle_read_event()
+ except ExitNow:
+ raise
+ except:
+ obj.handle_error()
+
+def write(obj):
+ try:
+ obj.handle_write_event()
+ except ExitNow:
+ raise
+ except:
+ obj.handle_error()
+
+def _exception (obj):
+ try:
+ obj.handle_expt_event()
+ except ExitNow:
+ raise
+ except:
+ obj.handle_error()
+
+def readwrite(obj, flags):
+ try:
+ if flags & (select.POLLIN | select.POLLPRI):
+ obj.handle_read_event()
+ if flags & select.POLLOUT:
+ obj.handle_write_event()
+ if flags & (select.POLLERR | select.POLLHUP | select.POLLNVAL):
+ obj.handle_expt_event()
+ except ExitNow:
+ 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)
+ if is_w:
+ w.append(fd)
+ if is_r or is_w:
+ e.append(fd)
+ if [] == r == w == e:
+ time.sleep(timeout)
+ else:
+ try:
+ r, w, e = select.select(r, w, e, timeout)
+ except select.error, err:
+ if err[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
+ if obj.writable():
+ 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[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 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 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
+ closing = False
+ addr = None
+
+ def __init__(self, sock=None, map=None):
+ if map is None:
+ self._map = socket_map
+ else:
+ self._map = map
+
+ if sock:
+ self.set_socket(sock, map)
+ # I think it should inherit this anyway
+ self.socket.setblocking(0)
+ self.connected = True
+ # XXX Does the constructor require that the socket passed
+ # be connected?
+ try:
+ self.addr = sock.getpeername()
+ except socket.error:
+ # The addr isn't crucial
+ pass
+ 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))
+
+ 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 map.has_key(fd):
+ #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
+ self.socket = socket.socket(family, type)
+ self.socket.setblocking(0)
+ self._fileno = self.socket.fileno()
+ self.add_channel()
+
+ def set_socket(self, sock, map=None):
+ self.socket = sock
+## self.__dict__['socket'] = sock
+ self._fileno = sock.fileno()
+ 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 = 1
+ return self.socket.listen(num)
+
+ def bind(self, addr):
+ self.addr = addr
+ return self.socket.bind(addr)
+
+ def connect(self, address):
+ self.connected = False
+ err = self.socket.connect_ex(address)
+ # XXX Should interpret Winsock return values
+ if err in (EINPROGRESS, EALREADY, EWOULDBLOCK):
+ return
+ if err in (0, EISCONN):
+ self.addr = address
+ self.connected = True
+ self.handle_connect()
+ 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()
+ return conn, addr
+ except socket.error, why:
+ if why[0] == EWOULDBLOCK:
+ pass
+ else:
+ raise
+
+ def send(self, data):
+ try:
+ result = self.socket.send(data)
+ return result
+ except socket.error, why:
+ if why[0] == EWOULDBLOCK:
+ return 0
+ else:
+ raise
+ return 0
+
+ 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[0] in [ECONNRESET, ENOTCONN, ESHUTDOWN]:
+ self.handle_close()
+ return ''
+ else:
+ raise
+
+ def close(self):
+ self.del_channel()
+ self.socket.close()
+
+ # cheap inheritance, used to pass all other attribute
+ # references to the underlying socket object.
+ def __getattr__(self, attr):
+ return getattr(self.socket, attr)
+
+ # 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 __debug__ or type != 'info':
+ print '%s: %s' % (type, message)
+
+ def handle_read_event(self):
+ if self.accepting:
+ # for an accepting socket, getting a read implies
+ # that we are connected
+ if not self.connected:
+ self.connected = True
+ self.handle_accept()
+ elif not self.connected:
+ self.handle_connect()
+ self.connected = True
+ self.handle_read()
+ else:
+ self.handle_read()
+
+ def handle_write_event(self):
+ # getting a write implies that we are connected
+ if not self.connected:
+ self.handle_connect()
+ self.connected = True
+ self.handle_write()
+
+ def handle_expt_event(self):
+ 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.close()
+
+ def handle_expt(self):
+ self.log_info('unhandled exception', '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 = []
+ assert tb # Must have a traceback
+ 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):
+ if map is None:
+ map = socket_map
+ for x in map.values():
+ x.socket.close()
+ 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.
+
+ def __init__(self, fd):
+ self.fd = fd
+
+ def recv(self, *args):
+ return os.read(self.fd, *args)
+
+ def send(self, *args):
+ return os.write(self.fd, *args)
+
+ 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
+ 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._fileno = fd
+ self.socket = file_wrapper(fd)
+ self.add_channel()
--- /dev/null
+++ b/sys/lib/python/atexit.py
@@ -1,0 +1,62 @@
+"""
+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
+ """
+ _exithandlers.append((func, targs, kargs))
+
+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")
--- /dev/null
+++ b/sys/lib/python/audiodev.py
@@ -1,0 +1,257 @@
+"""Classes for manipulating audio devices (currently only for Sun and SGI)"""
+
+__all__ = ["error","AudioDev"]
+
+class error(Exception):
+ pass
+
+class Play_Audio_sgi:
+ # Private instance variables
+## if 0: access frameratelist, nchannelslist, sampwidthlist, oldparams, \
+## params, config, inited_outrate, inited_width, \
+## inited_nchannels, port, converter, classinited: private
+
+ classinited = 0
+ frameratelist = nchannelslist = sampwidthlist = None
+
+ def initclass(self):
+ import AL
+ self.frameratelist = [
+ (48000, AL.RATE_48000),
+ (44100, AL.RATE_44100),
+ (32000, AL.RATE_32000),
+ (22050, AL.RATE_22050),
+ (16000, AL.RATE_16000),
+ (11025, AL.RATE_11025),
+ ( 8000, AL.RATE_8000),
+ ]
+ self.nchannelslist = [
+ (1, AL.MONO),
+ (2, AL.STEREO),
+ (4, AL.QUADRO),
+ ]
+ self.sampwidthlist = [
+ (1, AL.SAMPLE_8),
+ (2, AL.SAMPLE_16),
+ (3, AL.SAMPLE_24),
+ ]
+ self.classinited = 1
+
+ def __init__(self):
+ import al, AL
+ if not self.classinited:
+ self.initclass()
+ self.oldparams = []
+ self.params = [AL.OUTPUT_RATE, 0]
+ self.config = al.newconfig()
+ self.inited_outrate = 0
+ self.inited_width = 0
+ self.inited_nchannels = 0
+ self.converter = None
+ self.port = None
+ return
+
+ def __del__(self):
+ if self.port:
+ self.stop()
+ if self.oldparams:
+ import al, AL
+ al.setparams(AL.DEFAULT_DEVICE, self.oldparams)
+ self.oldparams = []
+
+ def wait(self):
+ if not self.port:
+ return
+ import time
+ while self.port.getfilled() > 0:
+ time.sleep(0.1)
+ self.stop()
+
+ def stop(self):
+ if self.port:
+ self.port.closeport()
+ self.port = None
+ if self.oldparams:
+ import al, AL
+ al.setparams(AL.DEFAULT_DEVICE, self.oldparams)
+ self.oldparams = []
+
+ def setoutrate(self, rate):
+ for (raw, cooked) in self.frameratelist:
+ if rate == raw:
+ self.params[1] = cooked
+ self.inited_outrate = 1
+ break
+ else:
+ raise error, 'bad output rate'
+
+ def setsampwidth(self, width):
+ for (raw, cooked) in self.sampwidthlist:
+ if width == raw:
+ self.config.setwidth(cooked)
+ self.inited_width = 1
+ break
+ else:
+ if width == 0:
+ import AL
+ self.inited_width = 0
+ self.config.setwidth(AL.SAMPLE_16)
+ self.converter = self.ulaw2lin
+ else:
+ raise error, 'bad sample width'
+
+ def setnchannels(self, nchannels):
+ for (raw, cooked) in self.nchannelslist:
+ if nchannels == raw:
+ self.config.setchannels(cooked)
+ self.inited_nchannels = 1
+ break
+ else:
+ raise error, 'bad # of channels'
+
+ def writeframes(self, data):
+ if not (self.inited_outrate and self.inited_nchannels):
+ raise error, 'params not specified'
+ if not self.port:
+ import al, AL
+ self.port = al.openport('Python', 'w', self.config)
+ self.oldparams = self.params[:]
+ al.getparams(AL.DEFAULT_DEVICE, self.oldparams)
+ al.setparams(AL.DEFAULT_DEVICE, self.params)
+ if self.converter:
+ data = self.converter(data)
+ self.port.writesamps(data)
+
+ def getfilled(self):
+ if self.port:
+ return self.port.getfilled()
+ else:
+ return 0
+
+ def getfillable(self):
+ if self.port:
+ return self.port.getfillable()
+ else:
+ return self.config.getqueuesize()
+
+ # private methods
+## if 0: access *: private
+
+ def ulaw2lin(self, data):
+ import audioop
+ return audioop.ulaw2lin(data, 2)
+
+class Play_Audio_sun:
+## if 0: access outrate, sampwidth, nchannels, inited_outrate, inited_width, \
+## inited_nchannels, converter: private
+
+ def __init__(self):
+ self.outrate = 0
+ self.sampwidth = 0
+ self.nchannels = 0
+ self.inited_outrate = 0
+ self.inited_width = 0
+ self.inited_nchannels = 0
+ self.converter = None
+ self.port = None
+ return
+
+ def __del__(self):
+ self.stop()
+
+ def setoutrate(self, rate):
+ self.outrate = rate
+ self.inited_outrate = 1
+
+ def setsampwidth(self, width):
+ self.sampwidth = width
+ self.inited_width = 1
+
+ def setnchannels(self, nchannels):
+ self.nchannels = nchannels
+ self.inited_nchannels = 1
+
+ def writeframes(self, data):
+ if not (self.inited_outrate and self.inited_width and self.inited_nchannels):
+ raise error, 'params not specified'
+ if not self.port:
+ import sunaudiodev, SUNAUDIODEV
+ self.port = sunaudiodev.open('w')
+ info = self.port.getinfo()
+ info.o_sample_rate = self.outrate
+ info.o_channels = self.nchannels
+ if self.sampwidth == 0:
+ info.o_precision = 8
+ self.o_encoding = SUNAUDIODEV.ENCODING_ULAW
+ # XXX Hack, hack -- leave defaults
+ else:
+ info.o_precision = 8 * self.sampwidth
+ info.o_encoding = SUNAUDIODEV.ENCODING_LINEAR
+ self.port.setinfo(info)
+ if self.converter:
+ data = self.converter(data)
+ self.port.write(data)
+
+ def wait(self):
+ if not self.port:
+ return
+ self.port.drain()
+ self.stop()
+
+ def stop(self):
+ if self.port:
+ self.port.flush()
+ self.port.close()
+ self.port = None
+
+ def getfilled(self):
+ if self.port:
+ return self.port.obufcount()
+ else:
+ return 0
+
+## # Nobody remembers what this method does, and it's broken. :-(
+## def getfillable(self):
+## return BUFFERSIZE - self.getfilled()
+
+def AudioDev():
+ # Dynamically try to import and use a platform specific module.
+ try:
+ import al
+ except ImportError:
+ try:
+ import sunaudiodev
+ return Play_Audio_sun()
+ except ImportError:
+ try:
+ import Audio_mac
+ except ImportError:
+ raise error, 'no audio device'
+ else:
+ return Audio_mac.Play_Audio_mac()
+ else:
+ return Play_Audio_sgi()
+
+def test(fn = None):
+ import sys
+ if sys.argv[1:]:
+ fn = sys.argv[1]
+ else:
+ fn = 'f:just samples:just.aif'
+ import aifc
+ af = aifc.open(fn, 'r')
+ print fn, af.getparams()
+ p = AudioDev()
+ p.setoutrate(af.getframerate())
+ p.setsampwidth(af.getsampwidth())
+ p.setnchannels(af.getnchannels())
+ BUFSIZ = af.getframerate()/af.getsampwidth()/af.getnchannels()
+ while 1:
+ data = af.readframes(BUFSIZ)
+ if not data: break
+ print len(data)
+ p.writeframes(data)
+ p.wait()
+
+if __name__ == '__main__':
+ test()
--- /dev/null
+++ b/sys/lib/python/base64.py
@@ -1,0 +1,359 @@
+#! /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."""
+ 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] != '-':
+ func(open(args[0], 'rb'), 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()
--- /dev/null
+++ b/sys/lib/python/bdb.py
@@ -1,0 +1,613 @@
+"""Debugger basics"""
+
+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):
+ self.breaks = {}
+ self.fncache = {}
+
+ 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.stopframe = None
+ self.returnframe = None
+ self.quitting = 0
+
+ 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:
+ self.user_return(frame, arg)
+ 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 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 frame is self.stopframe:
+ return True
+ 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.breaks.has_key(
+ self.canonic(frame.f_code.co_filename))
+
+ # 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_type, exc_value, exc_traceback)):
+ """This method is called if an exception occurs,
+ but only if we are to stop at or just below this level."""
+ pass
+
+ # Derived classes and clients can call the following methods
+ # to affect the stepping state.
+
+ def set_step(self):
+ """Stop after one line of code."""
+ self.stopframe = None
+ self.returnframe = None
+ self.quitting = 0
+
+ def set_next(self, frame):
+ """Stop on the next line in or below the given frame."""
+ self.stopframe = frame
+ self.returnframe = None
+ self.quitting = 0
+
+ def set_return(self, frame):
+ """Stop when returning from the given frame."""
+ self.stopframe = frame.f_back
+ self.returnframe = frame
+ self.quitting = 0
+
+ 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.stopframe = self.botframe
+ self.returnframe = None
+ self.quitting = 0
+ 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 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()
+ if not Breakpoint.bplist.has_key((filename, lineno)):
+ self.breaks[filename].remove(lineno)
+ if not self.breaks[filename]:
+ del self.breaks[filename]
+
+ 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
+ self.clear_break(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
+ 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)
+ 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:
+ 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:
+ 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:
+ 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 self.bplist.has_key((file, line)):
+ 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)
+ 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
--- /dev/null
+++ b/sys/lib/python/binhex.py
@@ -1,0 +1,527 @@
+"""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):
+ if type(ofp) == type(''):
+ ofname = ofp
+ ofp = open(ofname, 'w')
+ if os.name == 'mac':
+ fss = FSSpec(ofname)
+ fss.SetCreatorType('BnHq', 'TEXT')
+ 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
+ if os.name == 'mac':
+ ofss = FSSpec(out)
+ out = ofss.as_pathname()
+
+ 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()
+
+ if os.name == 'mac':
+ nfinfo = ofss.GetFInfo()
+ nfinfo.Creator = finfo.Creator
+ nfinfo.Type = finfo.Type
+ nfinfo.Flags = finfo.Flags
+ ofss.SetFInfo(nfinfo)
+
+ ifp.close()
+
+def _test():
+ if os.name == 'mac':
+ import macfs
+ fss, ok = macfs.PromptGetFile('File to convert:')
+ if not ok:
+ sys.exit(0)
+ fname = fss.as_pathname()
+ else:
+ fname = sys.argv[1]
+ binhex(fname, fname+'.hqx')
+ hexbin(fname+'.hqx', fname+'.viahqx')
+ #hexbin(fname, fname+'.unpacked')
+ sys.exit(1)
+
+if __name__ == '__main__':
+ _test()
--- /dev/null
+++ b/sys/lib/python/bisect.py
@@ -1,0 +1,84 @@
+"""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 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 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 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 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 bisect_right, bisect_left, insort_left, insort_right, insort, bisect
+except ImportError:
+ pass
--- /dev/null
+++ b/sys/lib/python/bsddb/__init__.py
@@ -1,0 +1,397 @@
+#----------------------------------------------------------------------
+# Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
+# and Andrew Kuchling. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# o Redistributions of source code must retain the above copyright
+# notice, this list of conditions, and the disclaimer that follows.
+#
+# o 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.
+#
+# o Neither the name of Digital Creations 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 DIGITAL CREATIONS 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 DIGITAL
+# CREATIONS 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.
+#----------------------------------------------------------------------
+
+
+"""Support for BerkeleyDB 3.3 through 4.4 with a simple interface.
+
+For the full featured object oriented interface use the bsddb.db module
+instead. It mirrors the Sleepycat BerkeleyDB C API.
+"""
+
+try:
+ if __name__ == 'bsddb3':
+ # import _pybsddb binary as it should be the more recent version from
+ # a standalone pybsddb addon package than the version included with
+ # python as bsddb._bsddb.
+ import _pybsddb
+ _bsddb = _pybsddb
+ from bsddb3.dbutils import DeadlockWrap as _DeadlockWrap
+ else:
+ import _bsddb
+ from bsddb.dbutils import DeadlockWrap as _DeadlockWrap
+except ImportError:
+ # Remove ourselves from sys.modules
+ import sys
+ del sys.modules[__name__]
+ raise
+
+# bsddb3 calls it db, but provide _db for backwards compatibility
+db = _db = _bsddb
+__version__ = db.__version__
+
+error = db.DBError # So bsddb.error will mean something...
+
+#----------------------------------------------------------------------
+
+import sys, os
+
+# for backwards compatibility with python versions older than 2.3, the
+# iterator interface is dynamically defined and added using a mixin
+# class. old python can't tokenize it due to the yield keyword.
+if sys.version >= '2.3':
+ import UserDict
+ from weakref import ref
+ exec """
+class _iter_mixin(UserDict.DictMixin):
+ def _make_iter_cursor(self):
+ cur = _DeadlockWrap(self.db.cursor)
+ key = id(cur)
+ self._cursor_refs[key] = ref(cur, self._gen_cref_cleaner(key))
+ return cur
+
+ def _gen_cref_cleaner(self, key):
+ # use generate the function for the weakref callback here
+ # to ensure that we do not hold a strict reference to cur
+ # in the callback.
+ return lambda ref: self._cursor_refs.pop(key, None)
+
+ def __iter__(self):
+ try:
+ cur = self._make_iter_cursor()
+
+ # FIXME-20031102-greg: race condition. cursor could
+ # be closed by another thread before this call.
+
+ # since we're only returning keys, we call the cursor
+ # methods with flags=0, dlen=0, dofs=0
+ key = _DeadlockWrap(cur.first, 0,0,0)[0]
+ yield key
+
+ next = cur.next
+ while 1:
+ try:
+ key = _DeadlockWrap(next, 0,0,0)[0]
+ yield key
+ except _bsddb.DBCursorClosedError:
+ cur = self._make_iter_cursor()
+ # FIXME-20031101-greg: race condition. cursor could
+ # be closed by another thread before this call.
+ _DeadlockWrap(cur.set, key,0,0,0)
+ next = cur.next
+ except _bsddb.DBNotFoundError:
+ return
+ except _bsddb.DBCursorClosedError:
+ # the database was modified during iteration. abort.
+ return
+
+ def iteritems(self):
+ if not self.db:
+ return
+ try:
+ cur = self._make_iter_cursor()
+
+ # FIXME-20031102-greg: race condition. cursor could
+ # be closed by another thread before this call.
+
+ kv = _DeadlockWrap(cur.first)
+ key = kv[0]
+ yield kv
+
+ next = cur.next
+ while 1:
+ try:
+ kv = _DeadlockWrap(next)
+ key = kv[0]
+ yield kv
+ except _bsddb.DBCursorClosedError:
+ cur = self._make_iter_cursor()
+ # FIXME-20031101-greg: race condition. cursor could
+ # be closed by another thread before this call.
+ _DeadlockWrap(cur.set, key,0,0,0)
+ next = cur.next
+ except _bsddb.DBNotFoundError:
+ return
+ except _bsddb.DBCursorClosedError:
+ # the database was modified during iteration. abort.
+ return
+"""
+else:
+ class _iter_mixin: pass
+
+
+class _DBWithCursor(_iter_mixin):
+ """
+ A simple wrapper around DB that makes it look like the bsddbobject in
+ the old module. It uses a cursor as needed to provide DB traversal.
+ """
+ def __init__(self, db):
+ self.db = db
+ self.db.set_get_returns_none(0)
+
+ # FIXME-20031101-greg: I believe there is still the potential
+ # for deadlocks in a multithreaded environment if someone
+ # attempts to use the any of the cursor interfaces in one
+ # thread while doing a put or delete in another thread. The
+ # reason is that _checkCursor and _closeCursors are not atomic
+ # operations. Doing our own locking around self.dbc,
+ # self.saved_dbc_key and self._cursor_refs could prevent this.
+ # TODO: A test case demonstrating the problem needs to be written.
+
+ # self.dbc is a DBCursor object used to implement the
+ # first/next/previous/last/set_location methods.
+ self.dbc = None
+ self.saved_dbc_key = None
+
+ # a collection of all DBCursor objects currently allocated
+ # by the _iter_mixin interface.
+ self._cursor_refs = {}
+
+ def __del__(self):
+ self.close()
+
+ def _checkCursor(self):
+ if self.dbc is None:
+ self.dbc = _DeadlockWrap(self.db.cursor)
+ if self.saved_dbc_key is not None:
+ _DeadlockWrap(self.dbc.set, self.saved_dbc_key)
+ self.saved_dbc_key = None
+
+ # This method is needed for all non-cursor DB calls to avoid
+ # BerkeleyDB deadlocks (due to being opened with DB_INIT_LOCK
+ # and DB_THREAD to be thread safe) when intermixing database
+ # operations that use the cursor internally with those that don't.
+ def _closeCursors(self, save=1):
+ if self.dbc:
+ c = self.dbc
+ self.dbc = None
+ if save:
+ try:
+ self.saved_dbc_key = _DeadlockWrap(c.current, 0,0,0)[0]
+ except db.DBError:
+ pass
+ _DeadlockWrap(c.close)
+ del c
+ for cref in self._cursor_refs.values():
+ c = cref()
+ if c is not None:
+ _DeadlockWrap(c.close)
+
+ def _checkOpen(self):
+ if self.db is None:
+ raise error, "BSDDB object has already been closed"
+
+ def isOpen(self):
+ return self.db is not None
+
+ def __len__(self):
+ self._checkOpen()
+ return _DeadlockWrap(lambda: len(self.db)) # len(self.db)
+
+ def __getitem__(self, key):
+ self._checkOpen()
+ return _DeadlockWrap(lambda: self.db[key]) # self.db[key]
+
+ def __setitem__(self, key, value):
+ self._checkOpen()
+ self._closeCursors()
+ def wrapF():
+ self.db[key] = value
+ _DeadlockWrap(wrapF) # self.db[key] = value
+
+ def __delitem__(self, key):
+ self._checkOpen()
+ self._closeCursors()
+ def wrapF():
+ del self.db[key]
+ _DeadlockWrap(wrapF) # del self.db[key]
+
+ def close(self):
+ self._closeCursors(save=0)
+ if self.dbc is not None:
+ _DeadlockWrap(self.dbc.close)
+ v = 0
+ if self.db is not None:
+ v = _DeadlockWrap(self.db.close)
+ self.dbc = None
+ self.db = None
+ return v
+
+ def keys(self):
+ self._checkOpen()
+ return _DeadlockWrap(self.db.keys)
+
+ def has_key(self, key):
+ self._checkOpen()
+ return _DeadlockWrap(self.db.has_key, key)
+
+ def set_location(self, key):
+ self._checkOpen()
+ self._checkCursor()
+ return _DeadlockWrap(self.dbc.set_range, key)
+
+ def next(self):
+ self._checkOpen()
+ self._checkCursor()
+ rv = _DeadlockWrap(self.dbc.next)
+ return rv
+
+ def previous(self):
+ self._checkOpen()
+ self._checkCursor()
+ rv = _DeadlockWrap(self.dbc.prev)
+ return rv
+
+ def first(self):
+ self._checkOpen()
+ self._checkCursor()
+ rv = _DeadlockWrap(self.dbc.first)
+ return rv
+
+ def last(self):
+ self._checkOpen()
+ self._checkCursor()
+ rv = _DeadlockWrap(self.dbc.last)
+ return rv
+
+ def sync(self):
+ self._checkOpen()
+ return _DeadlockWrap(self.db.sync)
+
+
+#----------------------------------------------------------------------
+# Compatibility object factory functions
+
+def hashopen(file, flag='c', mode=0666, pgsize=None, ffactor=None, nelem=None,
+ cachesize=None, lorder=None, hflags=0):
+
+ flags = _checkflag(flag, file)
+ e = _openDBEnv(cachesize)
+ d = db.DB(e)
+ d.set_flags(hflags)
+ if pgsize is not None: d.set_pagesize(pgsize)
+ if lorder is not None: d.set_lorder(lorder)
+ if ffactor is not None: d.set_h_ffactor(ffactor)
+ if nelem is not None: d.set_h_nelem(nelem)
+ d.open(file, db.DB_HASH, flags, mode)
+ return _DBWithCursor(d)
+
+#----------------------------------------------------------------------
+
+def btopen(file, flag='c', mode=0666,
+ btflags=0, cachesize=None, maxkeypage=None, minkeypage=None,
+ pgsize=None, lorder=None):
+
+ flags = _checkflag(flag, file)
+ e = _openDBEnv(cachesize)
+ d = db.DB(e)
+ if pgsize is not None: d.set_pagesize(pgsize)
+ if lorder is not None: d.set_lorder(lorder)
+ d.set_flags(btflags)
+ if minkeypage is not None: d.set_bt_minkey(minkeypage)
+ if maxkeypage is not None: d.set_bt_maxkey(maxkeypage)
+ d.open(file, db.DB_BTREE, flags, mode)
+ return _DBWithCursor(d)
+
+#----------------------------------------------------------------------
+
+
+def rnopen(file, flag='c', mode=0666,
+ rnflags=0, cachesize=None, pgsize=None, lorder=None,
+ rlen=None, delim=None, source=None, pad=None):
+
+ flags = _checkflag(flag, file)
+ e = _openDBEnv(cachesize)
+ d = db.DB(e)
+ if pgsize is not None: d.set_pagesize(pgsize)
+ if lorder is not None: d.set_lorder(lorder)
+ d.set_flags(rnflags)
+ if delim is not None: d.set_re_delim(delim)
+ if rlen is not None: d.set_re_len(rlen)
+ if source is not None: d.set_re_source(source)
+ if pad is not None: d.set_re_pad(pad)
+ d.open(file, db.DB_RECNO, flags, mode)
+ return _DBWithCursor(d)
+
+#----------------------------------------------------------------------
+
+def _openDBEnv(cachesize):
+ e = db.DBEnv()
+ if cachesize is not None:
+ if cachesize >= 20480:
+ e.set_cachesize(0, cachesize)
+ else:
+ raise error, "cachesize must be >= 20480"
+ e.set_lk_detect(db.DB_LOCK_DEFAULT)
+ e.open('.', db.DB_PRIVATE | db.DB_CREATE | db.DB_THREAD | db.DB_INIT_LOCK | db.DB_INIT_MPOOL)
+ return e
+
+def _checkflag(flag, file):
+ if flag == 'r':
+ flags = db.DB_RDONLY
+ elif flag == 'rw':
+ flags = 0
+ elif flag == 'w':
+ flags = db.DB_CREATE
+ elif flag == 'c':
+ flags = db.DB_CREATE
+ elif flag == 'n':
+ flags = db.DB_CREATE
+ #flags = db.DB_CREATE | db.DB_TRUNCATE
+ # we used db.DB_TRUNCATE flag for this before but BerkeleyDB
+ # 4.2.52 changed to disallowed truncate with txn environments.
+ if file is not None and os.path.isfile(file):
+ os.unlink(file)
+ else:
+ raise error, "flags should be one of 'r', 'w', 'c' or 'n'"
+ return flags | db.DB_THREAD
+
+#----------------------------------------------------------------------
+
+
+# This is a silly little hack that allows apps to continue to use the
+# DB_THREAD flag even on systems without threads without freaking out
+# BerkeleyDB.
+#
+# This assumes that if Python was built with thread support then
+# BerkeleyDB was too.
+
+try:
+ import thread
+ del thread
+ if db.version() < (3, 3, 0):
+ db.DB_THREAD = 0
+except ImportError:
+ db.DB_THREAD = 0
+
+#----------------------------------------------------------------------
--- /dev/null
+++ b/sys/lib/python/bsddb/db.py
@@ -1,0 +1,51 @@
+#----------------------------------------------------------------------
+# Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
+# and Andrew Kuchling. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# o Redistributions of source code must retain the above copyright
+# notice, this list of conditions, and the disclaimer that follows.
+#
+# o 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.
+#
+# o Neither the name of Digital Creations 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 DIGITAL CREATIONS 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 DIGITAL
+# CREATIONS 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.
+#----------------------------------------------------------------------
+
+
+# This module is just a placeholder for possible future expansion, in
+# case we ever want to augment the stuff in _db in any way. For now
+# it just simply imports everything from _db.
+
+if __name__.startswith('bsddb3.'):
+ # import _pybsddb binary as it should be the more recent version from
+ # a standalone pybsddb addon package than the version included with
+ # python as bsddb._bsddb.
+ from _pybsddb import *
+ from _pybsddb import __version__
+else:
+ from _bsddb import *
+ from _bsddb import __version__
+
+if version() < (3, 2, 0):
+ raise ImportError, "correct BerkeleyDB symbols not found. Perhaps python was statically linked with an older version?"
--- /dev/null
+++ b/sys/lib/python/bsddb/dbobj.py
@@ -1,0 +1,254 @@
+#-------------------------------------------------------------------------
+# This file contains real Python object wrappers for DB and DBEnv
+# C "objects" that can be usefully subclassed. The previous SWIG
+# based interface allowed this thanks to SWIG's shadow classes.
+# -- Gregory P. Smith
+#-------------------------------------------------------------------------
+#
+# (C) Copyright 2001 Autonomous Zone Industries
+#
+# License: This is free software. You may use this software for any
+# purpose including modification/redistribution, so long as
+# this header remains intact and that you do not claim any
+# rights of ownership or authorship of this software. This
+# software has been tested, but no warranty is expressed or
+# implied.
+#
+
+#
+# TODO it would be *really nice* to have an automatic shadow class populator
+# so that new methods don't need to be added here manually after being
+# added to _bsddb.c.
+#
+
+import db
+
+try:
+ from UserDict import DictMixin
+except ImportError:
+ # DictMixin is new in Python 2.3
+ class DictMixin: pass
+
+class DBEnv:
+ def __init__(self, *args, **kwargs):
+ self._cobj = apply(db.DBEnv, args, kwargs)
+
+ def close(self, *args, **kwargs):
+ return apply(self._cobj.close, args, kwargs)
+ def open(self, *args, **kwargs):
+ return apply(self._cobj.open, args, kwargs)
+ def remove(self, *args, **kwargs):
+ return apply(self._cobj.remove, args, kwargs)
+ def set_shm_key(self, *args, **kwargs):
+ return apply(self._cobj.set_shm_key, args, kwargs)
+ def set_cachesize(self, *args, **kwargs):
+ return apply(self._cobj.set_cachesize, args, kwargs)
+ def set_data_dir(self, *args, **kwargs):
+ return apply(self._cobj.set_data_dir, args, kwargs)
+ def set_flags(self, *args, **kwargs):
+ return apply(self._cobj.set_flags, args, kwargs)
+ def set_lg_bsize(self, *args, **kwargs):
+ return apply(self._cobj.set_lg_bsize, args, kwargs)
+ def set_lg_dir(self, *args, **kwargs):
+ return apply(self._cobj.set_lg_dir, args, kwargs)
+ def set_lg_max(self, *args, **kwargs):
+ return apply(self._cobj.set_lg_max, args, kwargs)
+ def set_lk_detect(self, *args, **kwargs):
+ return apply(self._cobj.set_lk_detect, args, kwargs)
+ if db.version() < (4,5):
+ def set_lk_max(self, *args, **kwargs):
+ return apply(self._cobj.set_lk_max, args, kwargs)
+ def set_lk_max_locks(self, *args, **kwargs):
+ return apply(self._cobj.set_lk_max_locks, args, kwargs)
+ def set_lk_max_lockers(self, *args, **kwargs):
+ return apply(self._cobj.set_lk_max_lockers, args, kwargs)
+ def set_lk_max_objects(self, *args, **kwargs):
+ return apply(self._cobj.set_lk_max_objects, args, kwargs)
+ def set_mp_mmapsize(self, *args, **kwargs):
+ return apply(self._cobj.set_mp_mmapsize, args, kwargs)
+ def set_timeout(self, *args, **kwargs):
+ return apply(self._cobj.set_timeout, args, kwargs)
+ def set_tmp_dir(self, *args, **kwargs):
+ return apply(self._cobj.set_tmp_dir, args, kwargs)
+ def txn_begin(self, *args, **kwargs):
+ return apply(self._cobj.txn_begin, args, kwargs)
+ def txn_checkpoint(self, *args, **kwargs):
+ return apply(self._cobj.txn_checkpoint, args, kwargs)
+ def txn_stat(self, *args, **kwargs):
+ return apply(self._cobj.txn_stat, args, kwargs)
+ def set_tx_max(self, *args, **kwargs):
+ return apply(self._cobj.set_tx_max, args, kwargs)
+ def set_tx_timestamp(self, *args, **kwargs):
+ return apply(self._cobj.set_tx_timestamp, args, kwargs)
+ def lock_detect(self, *args, **kwargs):
+ return apply(self._cobj.lock_detect, args, kwargs)
+ def lock_get(self, *args, **kwargs):
+ return apply(self._cobj.lock_get, args, kwargs)
+ def lock_id(self, *args, **kwargs):
+ return apply(self._cobj.lock_id, args, kwargs)
+ def lock_put(self, *args, **kwargs):
+ return apply(self._cobj.lock_put, args, kwargs)
+ def lock_stat(self, *args, **kwargs):
+ return apply(self._cobj.lock_stat, args, kwargs)
+ def log_archive(self, *args, **kwargs):
+ return apply(self._cobj.log_archive, args, kwargs)
+
+ def set_get_returns_none(self, *args, **kwargs):
+ return apply(self._cobj.set_get_returns_none, args, kwargs)
+
+ if db.version() >= (4,0):
+ def log_stat(self, *args, **kwargs):
+ return apply(self._cobj.log_stat, args, kwargs)
+
+ if db.version() >= (4,1):
+ def dbremove(self, *args, **kwargs):
+ return apply(self._cobj.dbremove, args, kwargs)
+ def dbrename(self, *args, **kwargs):
+ return apply(self._cobj.dbrename, args, kwargs)
+ def set_encrypt(self, *args, **kwargs):
+ return apply(self._cobj.set_encrypt, args, kwargs)
+
+ if db.version() >= (4,4):
+ def lsn_reset(self, *args, **kwargs):
+ return apply(self._cobj.lsn_reset, args, kwargs)
+
+
+class DB(DictMixin):
+ def __init__(self, dbenv, *args, **kwargs):
+ # give it the proper DBEnv C object that its expecting
+ self._cobj = apply(db.DB, (dbenv._cobj,) + args, kwargs)
+
+ # TODO are there other dict methods that need to be overridden?
+ def __len__(self):
+ return len(self._cobj)
+ def __getitem__(self, arg):
+ return self._cobj[arg]
+ def __setitem__(self, key, value):
+ self._cobj[key] = value
+ def __delitem__(self, arg):
+ del self._cobj[arg]
+
+ def append(self, *args, **kwargs):
+ return apply(self._cobj.append, args, kwargs)
+ def associate(self, *args, **kwargs):
+ return apply(self._cobj.associate, args, kwargs)
+ def close(self, *args, **kwargs):
+ return apply(self._cobj.close, args, kwargs)
+ def consume(self, *args, **kwargs):
+ return apply(self._cobj.consume, args, kwargs)
+ def consume_wait(self, *args, **kwargs):
+ return apply(self._cobj.consume_wait, args, kwargs)
+ def cursor(self, *args, **kwargs):
+ return apply(self._cobj.cursor, args, kwargs)
+ def delete(self, *args, **kwargs):
+ return apply(self._cobj.delete, args, kwargs)
+ def fd(self, *args, **kwargs):
+ return apply(self._cobj.fd, args, kwargs)
+ def get(self, *args, **kwargs):
+ return apply(self._cobj.get, args, kwargs)
+ def pget(self, *args, **kwargs):
+ return apply(self._cobj.pget, args, kwargs)
+ def get_both(self, *args, **kwargs):
+ return apply(self._cobj.get_both, args, kwargs)
+ def get_byteswapped(self, *args, **kwargs):
+ return apply(self._cobj.get_byteswapped, args, kwargs)
+ def get_size(self, *args, **kwargs):
+ return apply(self._cobj.get_size, args, kwargs)
+ def get_type(self, *args, **kwargs):
+ return apply(self._cobj.get_type, args, kwargs)
+ def join(self, *args, **kwargs):
+ return apply(self._cobj.join, args, kwargs)
+ def key_range(self, *args, **kwargs):
+ return apply(self._cobj.key_range, args, kwargs)
+ def has_key(self, *args, **kwargs):
+ return apply(self._cobj.has_key, args, kwargs)
+ def items(self, *args, **kwargs):
+ return apply(self._cobj.items, args, kwargs)
+ def keys(self, *args, **kwargs):
+ return apply(self._cobj.keys, args, kwargs)
+ def open(self, *args, **kwargs):
+ return apply(self._cobj.open, args, kwargs)
+ def put(self, *args, **kwargs):
+ return apply(self._cobj.put, args, kwargs)
+ def remove(self, *args, **kwargs):
+ return apply(self._cobj.remove, args, kwargs)
+ def rename(self, *args, **kwargs):
+ return apply(self._cobj.rename, args, kwargs)
+ def set_bt_minkey(self, *args, **kwargs):
+ return apply(self._cobj.set_bt_minkey, args, kwargs)
+ def set_bt_compare(self, *args, **kwargs):
+ return apply(self._cobj.set_bt_compare, args, kwargs)
+ def set_cachesize(self, *args, **kwargs):
+ return apply(self._cobj.set_cachesize, args, kwargs)
+ def set_flags(self, *args, **kwargs):
+ return apply(self._cobj.set_flags, args, kwargs)
+ def set_h_ffactor(self, *args, **kwargs):
+ return apply(self._cobj.set_h_ffactor, args, kwargs)
+ def set_h_nelem(self, *args, **kwargs):
+ return apply(self._cobj.set_h_nelem, args, kwargs)
+ def set_lorder(self, *args, **kwargs):
+ return apply(self._cobj.set_lorder, args, kwargs)
+ def set_pagesize(self, *args, **kwargs):
+ return apply(self._cobj.set_pagesize, args, kwargs)
+ def set_re_delim(self, *args, **kwargs):
+ return apply(self._cobj.set_re_delim, args, kwargs)
+ def set_re_len(self, *args, **kwargs):
+ return apply(self._cobj.set_re_len, args, kwargs)
+ def set_re_pad(self, *args, **kwargs):
+ return apply(self._cobj.set_re_pad, args, kwargs)
+ def set_re_source(self, *args, **kwargs):
+ return apply(self._cobj.set_re_source, args, kwargs)
+ def set_q_extentsize(self, *args, **kwargs):
+ return apply(self._cobj.set_q_extentsize, args, kwargs)
+ def stat(self, *args, **kwargs):
+ return apply(self._cobj.stat, args, kwargs)
+ def sync(self, *args, **kwargs):
+ return apply(self._cobj.sync, args, kwargs)
+ def type(self, *args, **kwargs):
+ return apply(self._cobj.type, args, kwargs)
+ def upgrade(self, *args, **kwargs):
+ return apply(self._cobj.upgrade, args, kwargs)
+ def values(self, *args, **kwargs):
+ return apply(self._cobj.values, args, kwargs)
+ def verify(self, *args, **kwargs):
+ return apply(self._cobj.verify, args, kwargs)
+ def set_get_returns_none(self, *args, **kwargs):
+ return apply(self._cobj.set_get_returns_none, args, kwargs)
+
+ if db.version() >= (4,1):
+ def set_encrypt(self, *args, **kwargs):
+ return apply(self._cobj.set_encrypt, args, kwargs)
+
+
+class DBSequence:
+ def __init__(self, *args, **kwargs):
+ self._cobj = apply(db.DBSequence, args, kwargs)
+
+ def close(self, *args, **kwargs):
+ return apply(self._cobj.close, args, kwargs)
+ def get(self, *args, **kwargs):
+ return apply(self._cobj.get, args, kwargs)
+ def get_dbp(self, *args, **kwargs):
+ return apply(self._cobj.get_dbp, args, kwargs)
+ def get_key(self, *args, **kwargs):
+ return apply(self._cobj.get_key, args, kwargs)
+ def init_value(self, *args, **kwargs):
+ return apply(self._cobj.init_value, args, kwargs)
+ def open(self, *args, **kwargs):
+ return apply(self._cobj.open, args, kwargs)
+ def remove(self, *args, **kwargs):
+ return apply(self._cobj.remove, args, kwargs)
+ def stat(self, *args, **kwargs):
+ return apply(self._cobj.stat, args, kwargs)
+ def set_cachesize(self, *args, **kwargs):
+ return apply(self._cobj.set_cachesize, args, kwargs)
+ def set_flags(self, *args, **kwargs):
+ return apply(self._cobj.set_flags, args, kwargs)
+ def set_range(self, *args, **kwargs):
+ return apply(self._cobj.set_range, args, kwargs)
+ def get_cachesize(self, *args, **kwargs):
+ return apply(self._cobj.get_cachesize, args, kwargs)
+ def get_flags(self, *args, **kwargs):
+ return apply(self._cobj.get_flags, args, kwargs)
+ def get_range(self, *args, **kwargs):
+ return apply(self._cobj.get_range, args, kwargs)
--- /dev/null
+++ b/sys/lib/python/bsddb/dbrecio.py
@@ -1,0 +1,190 @@
+
+"""
+File-like objects that read from or write to a bsddb record.
+
+This implements (nearly) all stdio methods.
+
+f = DBRecIO(db, key, txn=None)
+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
+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)
+
+Notes:
+- fileno() is left unimplemented so that code which uses it triggers
+ an exception early.
+- There's a simple test set (see end of this file) - not yet updated
+ for DBRecIO.
+- readline() is not implemented yet.
+
+
+From:
+ Itamar Shtull-Trauring <itamar@maxnm.com>
+"""
+
+import errno
+import string
+
+class DBRecIO:
+ def __init__(self, db, key, txn=None):
+ self.db = db
+ self.key = key
+ self.txn = txn
+ self.len = None
+ self.pos = 0
+ self.closed = 0
+ self.softspace = 0
+
+ def close(self):
+ if not self.closed:
+ self.closed = 1
+ del self.db, self.txn
+
+ def isatty(self):
+ if self.closed:
+ raise ValueError, "I/O operation on closed file"
+ return 0
+
+ def seek(self, pos, mode = 0):
+ if self.closed:
+ raise ValueError, "I/O operation on closed file"
+ if mode == 1:
+ pos = pos + self.pos
+ elif mode == 2:
+ pos = pos + self.len
+ self.pos = max(0, pos)
+
+ def tell(self):
+ if self.closed:
+ raise ValueError, "I/O operation on closed file"
+ return self.pos
+
+ def read(self, n = -1):
+ if self.closed:
+ raise ValueError, "I/O operation on closed file"
+ if n < 0:
+ newpos = self.len
+ else:
+ newpos = min(self.pos+n, self.len)
+
+ dlen = newpos - self.pos
+
+ r = self.db.get(self.key, txn=self.txn, dlen=dlen, doff=self.pos)
+ self.pos = newpos
+ return r
+
+ __fixme = """
+ def readline(self, length=None):
+ if self.closed:
+ raise ValueError, "I/O operation on closed file"
+ if self.buflist:
+ self.buf = self.buf + string.joinfields(self.buflist, '')
+ self.buflist = []
+ i = string.find(self.buf, '\n', self.pos)
+ if i < 0:
+ newpos = self.len
+ else:
+ newpos = i+1
+ if length is not None:
+ 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):
+ 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):
+ if self.closed:
+ raise ValueError, "I/O operation on closed file"
+ if size is None:
+ size = self.pos
+ elif size < 0:
+ raise IOError(errno.EINVAL,
+ "Negative size not allowed")
+ elif size < self.pos:
+ self.pos = size
+ self.db.put(self.key, "", txn=self.txn, dlen=self.len-size, doff=size)
+
+ def write(self, s):
+ if self.closed:
+ raise ValueError, "I/O operation on closed file"
+ if not s: return
+ if self.pos > self.len:
+ self.buflist.append('\0'*(self.pos - self.len))
+ self.len = self.pos
+ newpos = self.pos + len(s)
+ self.db.put(self.key, s, txn=self.txn, dlen=len(s), doff=self.pos)
+ self.pos = newpos
+
+ def writelines(self, list):
+ self.write(string.joinfields(list, ''))
+
+ def flush(self):
+ if self.closed:
+ raise ValueError, "I/O operation on closed file"
+
+
+"""
+# 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())
+ here = 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.close()
+
+if __name__ == '__main__':
+ _test()
+"""
--- /dev/null
+++ b/sys/lib/python/bsddb/dbshelve.py
@@ -1,0 +1,299 @@
+#!/bin/env python
+#------------------------------------------------------------------------
+# Copyright (c) 1997-2001 by Total Control Software
+# All Rights Reserved
+#------------------------------------------------------------------------
+#
+# Module Name: dbShelve.py
+#
+# Description: A reimplementation of the standard shelve.py that
+# forces the use of cPickle, and DB.
+#
+# Creation Date: 11/3/97 3:39:04PM
+#
+# License: This is free software. You may use this software for any
+# purpose including modification/redistribution, so long as
+# this header remains intact and that you do not claim any
+# rights of ownership or authorship of this software. This
+# software has been tested, but no warranty is expressed or
+# implied.
+#
+# 13-Dec-2000: Updated to be used with the new bsddb3 package.
+# Added DBShelfCursor class.
+#
+#------------------------------------------------------------------------
+
+"""Manage shelves of pickled objects using bsddb database files for the
+storage.
+"""
+
+#------------------------------------------------------------------------
+
+import cPickle
+try:
+ from UserDict import DictMixin
+except ImportError:
+ # DictMixin is new in Python 2.3
+ class DictMixin: pass
+import db
+
+#------------------------------------------------------------------------
+
+
+def open(filename, flags=db.DB_CREATE, mode=0660, filetype=db.DB_HASH,
+ dbenv=None, dbname=None):
+ """
+ A simple factory function for compatibility with the standard
+ shleve.py module. It can be used like this, where key is a string
+ and data is a pickleable object:
+
+ from bsddb import dbshelve
+ db = dbshelve.open(filename)
+
+ db[key] = data
+
+ db.close()
+ """
+ if type(flags) == type(''):
+ sflag = flags
+ if sflag == 'r':
+ flags = db.DB_RDONLY
+ elif sflag == 'rw':
+ flags = 0
+ elif sflag == 'w':
+ flags = db.DB_CREATE
+ elif sflag == 'c':
+ flags = db.DB_CREATE
+ elif sflag == 'n':
+ flags = db.DB_TRUNCATE | db.DB_CREATE
+ else:
+ raise db.DBError, "flags should be one of 'r', 'w', 'c' or 'n' or use the bsddb.db.DB_* flags"
+
+ d = DBShelf(dbenv)
+ d.open(filename, dbname, filetype, flags, mode)
+ return d
+
+#---------------------------------------------------------------------------
+
+class DBShelf(DictMixin):
+ """A shelf to hold pickled objects, built upon a bsddb DB object. It
+ automatically pickles/unpickles data objects going to/from the DB.
+ """
+ def __init__(self, dbenv=None):
+ self.db = db.DB(dbenv)
+ self.binary = 1
+
+
+ def __del__(self):
+ self.close()
+
+
+ def __getattr__(self, name):
+ """Many methods we can just pass through to the DB object.
+ (See below)
+ """
+ return getattr(self.db, name)
+
+
+ #-----------------------------------
+ # Dictionary access methods
+
+ def __len__(self):
+ return len(self.db)
+
+
+ def __getitem__(self, key):
+ data = self.db[key]
+ return cPickle.loads(data)
+
+
+ def __setitem__(self, key, value):
+ data = cPickle.dumps(value, self.binary)
+ self.db[key] = data
+
+
+ def __delitem__(self, key):
+ del self.db[key]
+
+
+ def keys(self, txn=None):
+ if txn != None:
+ return self.db.keys(txn)
+ else:
+ return self.db.keys()
+
+
+ def items(self, txn=None):
+ if txn != None:
+ items = self.db.items(txn)
+ else:
+ items = self.db.items()
+ newitems = []
+
+ for k, v in items:
+ newitems.append( (k, cPickle.loads(v)) )
+ return newitems
+
+ def values(self, txn=None):
+ if txn != None:
+ values = self.db.values(txn)
+ else:
+ values = self.db.values()
+
+ return map(cPickle.loads, values)
+
+ #-----------------------------------
+ # Other methods
+
+ def __append(self, value, txn=None):
+ data = cPickle.dumps(value, self.binary)
+ return self.db.append(data, txn)
+
+ def append(self, value, txn=None):
+ if self.get_type() != db.DB_RECNO:
+ self.append = self.__append
+ return self.append(value, txn=txn)
+ raise db.DBError, "append() only supported when dbshelve opened with filetype=dbshelve.db.DB_RECNO"
+
+
+ def associate(self, secondaryDB, callback, flags=0):
+ def _shelf_callback(priKey, priData, realCallback=callback):
+ data = cPickle.loads(priData)
+ return realCallback(priKey, data)
+ return self.db.associate(secondaryDB, _shelf_callback, flags)
+
+
+ #def get(self, key, default=None, txn=None, flags=0):
+ def get(self, *args, **kw):
+ # We do it with *args and **kw so if the default value wasn't
+ # given nothing is passed to the extension module. That way
+ # an exception can be raised if set_get_returns_none is turned
+ # off.
+ data = apply(self.db.get, args, kw)
+ try:
+ return cPickle.loads(data)
+ except (TypeError, cPickle.UnpicklingError):
+ return data # we may be getting the default value, or None,
+ # so it doesn't need unpickled.
+
+ def get_both(self, key, value, txn=None, flags=0):
+ data = cPickle.dumps(value, self.binary)
+ data = self.db.get(key, data, txn, flags)
+ return cPickle.loads(data)
+
+
+ def cursor(self, txn=None, flags=0):
+ c = DBShelfCursor(self.db.cursor(txn, flags))
+ c.binary = self.binary
+ return c
+
+
+ def put(self, key, value, txn=None, flags=0):
+ data = cPickle.dumps(value, self.binary)
+ return self.db.put(key, data, txn, flags)
+
+
+ def join(self, cursorList, flags=0):
+ raise NotImplementedError
+
+
+ #----------------------------------------------
+ # Methods allowed to pass-through to self.db
+ #
+ # close, delete, fd, get_byteswapped, get_type, has_key,
+ # key_range, open, remove, rename, stat, sync,
+ # upgrade, verify, and all set_* methods.
+
+
+#---------------------------------------------------------------------------
+
+class DBShelfCursor:
+ """
+ """
+ def __init__(self, cursor):
+ self.dbc = cursor
+
+ def __del__(self):
+ self.close()
+
+
+ def __getattr__(self, name):
+ """Some methods we can just pass through to the cursor object. (See below)"""
+ return getattr(self.dbc, name)
+
+
+ #----------------------------------------------
+
+ def dup(self, flags=0):
+ return DBShelfCursor(self.dbc.dup(flags))
+
+
+ def put(self, key, value, flags=0):
+ data = cPickle.dumps(value, self.binary)
+ return self.dbc.put(key, data, flags)
+
+
+ def get(self, *args):
+ count = len(args) # a method overloading hack
+ method = getattr(self, 'get_%d' % count)
+ apply(method, args)
+
+ def get_1(self, flags):
+ rec = self.dbc.get(flags)
+ return self._extract(rec)
+
+ def get_2(self, key, flags):
+ rec = self.dbc.get(key, flags)
+ return self._extract(rec)
+
+ def get_3(self, key, value, flags):
+ data = cPickle.dumps(value, self.binary)
+ rec = self.dbc.get(key, flags)
+ return self._extract(rec)
+
+
+ def current(self, flags=0): return self.get_1(flags|db.DB_CURRENT)
+ def first(self, flags=0): return self.get_1(flags|db.DB_FIRST)
+ def last(self, flags=0): return self.get_1(flags|db.DB_LAST)
+ def next(self, flags=0): return self.get_1(flags|db.DB_NEXT)
+ def prev(self, flags=0): return self.get_1(flags|db.DB_PREV)
+ def consume(self, flags=0): return self.get_1(flags|db.DB_CONSUME)
+ def next_dup(self, flags=0): return self.get_1(flags|db.DB_NEXT_DUP)
+ def next_nodup(self, flags=0): return self.get_1(flags|db.DB_NEXT_NODUP)
+ def prev_nodup(self, flags=0): return self.get_1(flags|db.DB_PREV_NODUP)
+
+
+ def get_both(self, key, value, flags=0):
+ data = cPickle.dumps(value, self.binary)
+ rec = self.dbc.get_both(key, flags)
+ return self._extract(rec)
+
+
+ def set(self, key, flags=0):
+ rec = self.dbc.set(key, flags)
+ return self._extract(rec)
+
+ def set_range(self, key, flags=0):
+ rec = self.dbc.set_range(key, flags)
+ return self._extract(rec)
+
+ def set_recno(self, recno, flags=0):
+ rec = self.dbc.set_recno(recno, flags)
+ return self._extract(rec)
+
+ set_both = get_both
+
+ def _extract(self, rec):
+ if rec is None:
+ return None
+ else:
+ key, data = rec
+ return key, cPickle.loads(data)
+
+ #----------------------------------------------
+ # Methods allowed to pass-through to self.dbc
+ #
+ # close, count, delete, get_recno, join_item
+
+
+#---------------------------------------------------------------------------
--- /dev/null
+++ b/sys/lib/python/bsddb/dbtables.py
@@ -1,0 +1,706 @@
+#-----------------------------------------------------------------------
+#
+# Copyright (C) 2000, 2001 by Autonomous Zone Industries
+# Copyright (C) 2002 Gregory P. Smith
+#
+# License: This is free software. You may use this software for any
+# purpose including modification/redistribution, so long as
+# this header remains intact and that you do not claim any
+# rights of ownership or authorship of this software. This
+# software has been tested, but no warranty is expressed or
+# implied.
+#
+# -- Gregory P. Smith <greg@electricrain.com>
+
+# This provides a simple database table interface built on top of
+# the Python BerkeleyDB 3 interface.
+#
+_cvsid = '$Id: dbtables.py 46858 2006-06-11 08:35:14Z neal.norwitz $'
+
+import re
+import sys
+import copy
+import xdrlib
+import random
+from types import ListType, StringType
+import cPickle as pickle
+
+try:
+ # For Pythons w/distutils pybsddb
+ from bsddb3.db import *
+except ImportError:
+ # For Python 2.3
+ from bsddb.db import *
+
+# XXX(nnorwitz): is this correct? DBIncompleteError is conditional in _bsddb.c
+try:
+ DBIncompleteError
+except NameError:
+ class DBIncompleteError(Exception):
+ pass
+
+class TableDBError(StandardError):
+ pass
+class TableAlreadyExists(TableDBError):
+ pass
+
+
+class Cond:
+ """This condition matches everything"""
+ def __call__(self, s):
+ return 1
+
+class ExactCond(Cond):
+ """Acts as an exact match condition function"""
+ def __init__(self, strtomatch):
+ self.strtomatch = strtomatch
+ def __call__(self, s):
+ return s == self.strtomatch
+
+class PrefixCond(Cond):
+ """Acts as a condition function for matching a string prefix"""
+ def __init__(self, prefix):
+ self.prefix = prefix
+ def __call__(self, s):
+ return s[:len(self.prefix)] == self.prefix
+
+class PostfixCond(Cond):
+ """Acts as a condition function for matching a string postfix"""
+ def __init__(self, postfix):
+ self.postfix = postfix
+ def __call__(self, s):
+ return s[-len(self.postfix):] == self.postfix
+
+class LikeCond(Cond):
+ """
+ Acts as a function that will match using an SQL 'LIKE' style
+ string. Case insensitive and % signs are wild cards.
+ This isn't perfect but it should work for the simple common cases.
+ """
+ def __init__(self, likestr, re_flags=re.IGNORECASE):
+ # escape python re characters
+ chars_to_escape = '.*+()[]?'
+ for char in chars_to_escape :
+ likestr = likestr.replace(char, '\\'+char)
+ # convert %s to wildcards
+ self.likestr = likestr.replace('%', '.*')
+ self.re = re.compile('^'+self.likestr+'$', re_flags)
+ def __call__(self, s):
+ return self.re.match(s)
+
+#
+# keys used to store database metadata
+#
+_table_names_key = '__TABLE_NAMES__' # list of the tables in this db
+_columns = '._COLUMNS__' # table_name+this key contains a list of columns
+
+def _columns_key(table):
+ return table + _columns
+
+#
+# these keys are found within table sub databases
+#
+_data = '._DATA_.' # this+column+this+rowid key contains table data
+_rowid = '._ROWID_.' # this+rowid+this key contains a unique entry for each
+ # row in the table. (no data is stored)
+_rowid_str_len = 8 # length in bytes of the unique rowid strings
+
+def _data_key(table, col, rowid):
+ return table + _data + col + _data + rowid
+
+def _search_col_data_key(table, col):
+ return table + _data + col + _data
+
+def _search_all_data_key(table):
+ return table + _data
+
+def _rowid_key(table, rowid):
+ return table + _rowid + rowid + _rowid
+
+def _search_rowid_key(table):
+ return table + _rowid
+
+def contains_metastrings(s) :
+ """Verify that the given string does not contain any
+ metadata strings that might interfere with dbtables database operation.
+ """
+ if (s.find(_table_names_key) >= 0 or
+ s.find(_columns) >= 0 or
+ s.find(_data) >= 0 or
+ s.find(_rowid) >= 0):
+ # Then
+ return 1
+ else:
+ return 0
+
+
+class bsdTableDB :
+ def __init__(self, filename, dbhome, create=0, truncate=0, mode=0600,
+ recover=0, dbflags=0):
+ """bsdTableDB(filename, dbhome, create=0, truncate=0, mode=0600)
+
+ Open database name in the dbhome BerkeleyDB directory.
+ Use keyword arguments when calling this constructor.
+ """
+ self.db = None
+ myflags = DB_THREAD
+ if create:
+ myflags |= DB_CREATE
+ flagsforenv = (DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_LOG |
+ DB_INIT_TXN | dbflags)
+ # DB_AUTO_COMMIT isn't a valid flag for env.open()
+ try:
+ dbflags |= DB_AUTO_COMMIT
+ except AttributeError:
+ pass
+ if recover:
+ flagsforenv = flagsforenv | DB_RECOVER
+ self.env = DBEnv()
+ # enable auto deadlock avoidance
+ self.env.set_lk_detect(DB_LOCK_DEFAULT)
+ self.env.open(dbhome, myflags | flagsforenv)
+ if truncate:
+ myflags |= DB_TRUNCATE
+ self.db = DB(self.env)
+ # this code relies on DBCursor.set* methods to raise exceptions
+ # rather than returning None
+ self.db.set_get_returns_none(1)
+ # allow duplicate entries [warning: be careful w/ metadata]
+ self.db.set_flags(DB_DUP)
+ self.db.open(filename, DB_BTREE, dbflags | myflags, mode)
+ self.dbfilename = filename
+ # Initialize the table names list if this is a new database
+ txn = self.env.txn_begin()
+ try:
+ if not self.db.has_key(_table_names_key, txn):
+ self.db.put(_table_names_key, pickle.dumps([], 1), txn=txn)
+ # Yes, bare except
+ except:
+ txn.abort()
+ raise
+ else:
+ txn.commit()
+ # TODO verify more of the database's metadata?
+ self.__tablecolumns = {}
+
+ def __del__(self):
+ self.close()
+
+ def close(self):
+ if self.db is not None:
+ self.db.close()
+ self.db = None
+ if self.env is not None:
+ self.env.close()
+ self.env = None
+
+ def checkpoint(self, mins=0):
+ try:
+ self.env.txn_checkpoint(mins)
+ except DBIncompleteError:
+ pass
+
+ def sync(self):
+ try:
+ self.db.sync()
+ except DBIncompleteError:
+ pass
+
+ def _db_print(self) :
+ """Print the database to stdout for debugging"""
+ print "******** Printing raw database for debugging ********"
+ cur = self.db.cursor()
+ try:
+ key, data = cur.first()
+ while 1:
+ print repr({key: data})
+ next = cur.next()
+ if next:
+ key, data = next
+ else:
+ cur.close()
+ return
+ except DBNotFoundError:
+ cur.close()
+
+
+ def CreateTable(self, table, columns):
+ """CreateTable(table, columns) - Create a new table in the database.
+
+ raises TableDBError if it already exists or for other DB errors.
+ """
+ assert isinstance(columns, ListType)
+ txn = None
+ try:
+ # checking sanity of the table and column names here on
+ # table creation will prevent problems elsewhere.
+ if contains_metastrings(table):
+ raise ValueError(
+ "bad table name: contains reserved metastrings")
+ for column in columns :
+ if contains_metastrings(column):
+ raise ValueError(
+ "bad column name: contains reserved metastrings")
+
+ columnlist_key = _columns_key(table)
+ if self.db.has_key(columnlist_key):
+ raise TableAlreadyExists, "table already exists"
+
+ txn = self.env.txn_begin()
+ # store the table's column info
+ self.db.put(columnlist_key, pickle.dumps(columns, 1), txn=txn)
+
+ # add the table name to the tablelist
+ tablelist = pickle.loads(self.db.get(_table_names_key, txn=txn,
+ flags=DB_RMW))
+ tablelist.append(table)
+ # delete 1st, in case we opened with DB_DUP
+ self.db.delete(_table_names_key, txn)
+ self.db.put(_table_names_key, pickle.dumps(tablelist, 1), txn=txn)
+
+ txn.commit()
+ txn = None
+ except DBError, dberror:
+ if txn:
+ txn.abort()
+ raise TableDBError, dberror[1]
+
+
+ def ListTableColumns(self, table):
+ """Return a list of columns in the given table.
+ [] if the table doesn't exist.
+ """
+ assert isinstance(table, StringType)
+ if contains_metastrings(table):
+ raise ValueError, "bad table name: contains reserved metastrings"
+
+ columnlist_key = _columns_key(table)
+ if not self.db.has_key(columnlist_key):
+ return []
+ pickledcolumnlist = self.db.get(columnlist_key)
+ if pickledcolumnlist:
+ return pickle.loads(pickledcolumnlist)
+ else:
+ return []
+
+ def ListTables(self):
+ """Return a list of tables in this database."""
+ pickledtablelist = self.db.get(_table_names_key)
+ if pickledtablelist:
+ return pickle.loads(pickledtablelist)
+ else:
+ return []
+
+ def CreateOrExtendTable(self, table, columns):
+ """CreateOrExtendTable(table, columns)
+
+ Create a new table in the database.
+
+ If a table of this name already exists, extend it to have any
+ additional columns present in the given list as well as
+ all of its current columns.
+ """
+ assert isinstance(columns, ListType)
+ try:
+ self.CreateTable(table, columns)
+ except TableAlreadyExists:
+ # the table already existed, add any new columns
+ txn = None
+ try:
+ columnlist_key = _columns_key(table)
+ txn = self.env.txn_begin()
+
+ # load the current column list
+ oldcolumnlist = pickle.loads(
+ self.db.get(columnlist_key, txn=txn, flags=DB_RMW))
+ # create a hash table for fast lookups of column names in the
+ # loop below
+ oldcolumnhash = {}
+ for c in oldcolumnlist:
+ oldcolumnhash[c] = c
+
+ # create a new column list containing both the old and new
+ # column names
+ newcolumnlist = copy.copy(oldcolumnlist)
+ for c in columns:
+ if not oldcolumnhash.has_key(c):
+ newcolumnlist.append(c)
+
+ # store the table's new extended column list
+ if newcolumnlist != oldcolumnlist :
+ # delete the old one first since we opened with DB_DUP
+ self.db.delete(columnlist_key, txn)
+ self.db.put(columnlist_key,
+ pickle.dumps(newcolumnlist, 1),
+ txn=txn)
+
+ txn.commit()
+ txn = None
+
+ self.__load_column_info(table)
+ except DBError, dberror:
+ if txn:
+ txn.abort()
+ raise TableDBError, dberror[1]
+
+
+ def __load_column_info(self, table) :
+ """initialize the self.__tablecolumns dict"""
+ # check the column names
+ try:
+ tcolpickles = self.db.get(_columns_key(table))
+ except DBNotFoundError:
+ raise TableDBError, "unknown table: %r" % (table,)
+ if not tcolpickles:
+ raise TableDBError, "unknown table: %r" % (table,)
+ self.__tablecolumns[table] = pickle.loads(tcolpickles)
+
+ def __new_rowid(self, table, txn) :
+ """Create a new unique row identifier"""
+ unique = 0
+ while not unique:
+ # Generate a random 64-bit row ID string
+ # (note: this code has <64 bits of randomness
+ # but it's plenty for our database id needs!)
+ p = xdrlib.Packer()
+ p.pack_int(int(random.random()*2147483647))
+ p.pack_int(int(random.random()*2147483647))
+ newid = p.get_buffer()
+
+ # Guarantee uniqueness by adding this key to the database
+ try:
+ self.db.put(_rowid_key(table, newid), None, txn=txn,
+ flags=DB_NOOVERWRITE)
+ except DBKeyExistError:
+ pass
+ else:
+ unique = 1
+
+ return newid
+
+
+ def Insert(self, table, rowdict) :
+ """Insert(table, datadict) - Insert a new row into the table
+ using the keys+values from rowdict as the column values.
+ """
+ txn = None
+ try:
+ if not self.db.has_key(_columns_key(table)):
+ raise TableDBError, "unknown table"
+
+ # check the validity of each column name
+ if not self.__tablecolumns.has_key(table):
+ self.__load_column_info(table)
+ for column in rowdict.keys() :
+ if not self.__tablecolumns[table].count(column):
+ raise TableDBError, "unknown column: %r" % (column,)
+
+ # get a unique row identifier for this row
+ txn = self.env.txn_begin()
+ rowid = self.__new_rowid(table, txn=txn)
+
+ # insert the row values into the table database
+ for column, dataitem in rowdict.items():
+ # store the value
+ self.db.put(_data_key(table, column, rowid), dataitem, txn=txn)
+
+ txn.commit()
+ txn = None
+
+ except DBError, dberror:
+ # WIBNI we could just abort the txn and re-raise the exception?
+ # But no, because TableDBError is not related to DBError via
+ # inheritance, so it would be backwards incompatible. Do the next
+ # best thing.
+ info = sys.exc_info()
+ if txn:
+ txn.abort()
+ self.db.delete(_rowid_key(table, rowid))
+ raise TableDBError, dberror[1], info[2]
+
+
+ def Modify(self, table, conditions={}, mappings={}):
+ """Modify(table, conditions={}, mappings={}) - Modify items in rows matching 'conditions' using mapping functions in 'mappings'
+
+ * table - the table name
+ * conditions - a dictionary keyed on column names containing
+ a condition callable expecting the data string as an
+ argument and returning a boolean.
+ * mappings - a dictionary keyed on column names containing a
+ condition callable expecting the data string as an argument and
+ returning the new string for that column.
+ """
+ try:
+ matching_rowids = self.__Select(table, [], conditions)
+
+ # modify only requested columns
+ columns = mappings.keys()
+ for rowid in matching_rowids.keys():
+ txn = None
+ try:
+ for column in columns:
+ txn = self.env.txn_begin()
+ # modify the requested column
+ try:
+ dataitem = self.db.get(
+ _data_key(table, column, rowid),
+ txn)
+ self.db.delete(
+ _data_key(table, column, rowid),
+ txn)
+ except DBNotFoundError:
+ # XXXXXXX row key somehow didn't exist, assume no
+ # error
+ dataitem = None
+ dataitem = mappings[column](dataitem)
+ if dataitem <> None:
+ self.db.put(
+ _data_key(table, column, rowid),
+ dataitem, txn=txn)
+ txn.commit()
+ txn = None
+
+ # catch all exceptions here since we call unknown callables
+ except:
+ if txn:
+ txn.abort()
+ raise
+
+ except DBError, dberror:
+ raise TableDBError, dberror[1]
+
+ def Delete(self, table, conditions={}):
+ """Delete(table, conditions) - Delete items matching the given
+ conditions from the table.
+
+ * conditions - a dictionary keyed on column names containing
+ condition functions expecting the data string as an
+ argument and returning a boolean.
+ """
+ try:
+ matching_rowids = self.__Select(table, [], conditions)
+
+ # delete row data from all columns
+ columns = self.__tablecolumns[table]
+ for rowid in matching_rowids.keys():
+ txn = None
+ try:
+ txn = self.env.txn_begin()
+ for column in columns:
+ # delete the data key
+ try:
+ self.db.delete(_data_key(table, column, rowid),
+ txn)
+ except DBNotFoundError:
+ # XXXXXXX column may not exist, assume no error
+ pass
+
+ try:
+ self.db.delete(_rowid_key(table, rowid), txn)
+ except DBNotFoundError:
+ # XXXXXXX row key somehow didn't exist, assume no error
+ pass
+ txn.commit()
+ txn = None
+ except DBError, dberror:
+ if txn:
+ txn.abort()
+ raise
+ except DBError, dberror:
+ raise TableDBError, dberror[1]
+
+
+ def Select(self, table, columns, conditions={}):
+ """Select(table, columns, conditions) - retrieve specific row data
+ Returns a list of row column->value mapping dictionaries.
+
+ * columns - a list of which column data to return. If
+ columns is None, all columns will be returned.
+ * conditions - a dictionary keyed on column names
+ containing callable conditions expecting the data string as an
+ argument and returning a boolean.
+ """
+ try:
+ if not self.__tablecolumns.has_key(table):
+ self.__load_column_info(table)
+ if columns is None:
+ columns = self.__tablecolumns[table]
+ matching_rowids = self.__Select(table, columns, conditions)
+ except DBError, dberror:
+ raise TableDBError, dberror[1]
+ # return the matches as a list of dictionaries
+ return matching_rowids.values()
+
+
+ def __Select(self, table, columns, conditions):
+ """__Select() - Used to implement Select and Delete (above)
+ Returns a dictionary keyed on rowids containing dicts
+ holding the row data for columns listed in the columns param
+ that match the given conditions.
+ * conditions is a dictionary keyed on column names
+ containing callable conditions expecting the data string as an
+ argument and returning a boolean.
+ """
+ # check the validity of each column name
+ if not self.__tablecolumns.has_key(table):
+ self.__load_column_info(table)
+ if columns is None:
+ columns = self.tablecolumns[table]
+ for column in (columns + conditions.keys()):
+ if not self.__tablecolumns[table].count(column):
+ raise TableDBError, "unknown column: %r" % (column,)
+
+ # keyed on rows that match so far, containings dicts keyed on
+ # column names containing the data for that row and column.
+ matching_rowids = {}
+ # keys are rowids that do not match
+ rejected_rowids = {}
+
+ # attempt to sort the conditions in such a way as to minimize full
+ # column lookups
+ def cmp_conditions(atuple, btuple):
+ a = atuple[1]
+ b = btuple[1]
+ if type(a) is type(b):
+ if isinstance(a, PrefixCond) and isinstance(b, PrefixCond):
+ # longest prefix first
+ return cmp(len(b.prefix), len(a.prefix))
+ if isinstance(a, LikeCond) and isinstance(b, LikeCond):
+ # longest likestr first
+ return cmp(len(b.likestr), len(a.likestr))
+ return 0
+ if isinstance(a, ExactCond):
+ return -1
+ if isinstance(b, ExactCond):
+ return 1
+ if isinstance(a, PrefixCond):
+ return -1
+ if isinstance(b, PrefixCond):
+ return 1
+ # leave all unknown condition callables alone as equals
+ return 0
+
+ conditionlist = conditions.items()
+ conditionlist.sort(cmp_conditions)
+
+ # Apply conditions to column data to find what we want
+ cur = self.db.cursor()
+ column_num = -1
+ for column, condition in conditionlist:
+ column_num = column_num + 1
+ searchkey = _search_col_data_key(table, column)
+ # speedup: don't linear search columns within loop
+ if column in columns:
+ savethiscolumndata = 1 # save the data for return
+ else:
+ savethiscolumndata = 0 # data only used for selection
+
+ try:
+ key, data = cur.set_range(searchkey)
+ while key[:len(searchkey)] == searchkey:
+ # extract the rowid from the key
+ rowid = key[-_rowid_str_len:]
+
+ if not rejected_rowids.has_key(rowid):
+ # if no condition was specified or the condition
+ # succeeds, add row to our match list.
+ if not condition or condition(data):
+ if not matching_rowids.has_key(rowid):
+ matching_rowids[rowid] = {}
+ if savethiscolumndata:
+ matching_rowids[rowid][column] = data
+ else:
+ if matching_rowids.has_key(rowid):
+ del matching_rowids[rowid]
+ rejected_rowids[rowid] = rowid
+
+ key, data = cur.next()
+
+ except DBError, dberror:
+ if dberror[0] != DB_NOTFOUND:
+ raise
+ continue
+
+ cur.close()
+
+ # we're done selecting rows, garbage collect the reject list
+ del rejected_rowids
+
+ # extract any remaining desired column data from the
+ # database for the matching rows.
+ if len(columns) > 0:
+ for rowid, rowdata in matching_rowids.items():
+ for column in columns:
+ if rowdata.has_key(column):
+ continue
+ try:
+ rowdata[column] = self.db.get(
+ _data_key(table, column, rowid))
+ except DBError, dberror:
+ if dberror[0] != DB_NOTFOUND:
+ raise
+ rowdata[column] = None
+
+ # return the matches
+ return matching_rowids
+
+
+ def Drop(self, table):
+ """Remove an entire table from the database"""
+ txn = None
+ try:
+ txn = self.env.txn_begin()
+
+ # delete the column list
+ self.db.delete(_columns_key(table), txn)
+
+ cur = self.db.cursor(txn)
+
+ # delete all keys containing this tables column and row info
+ table_key = _search_all_data_key(table)
+ while 1:
+ try:
+ key, data = cur.set_range(table_key)
+ except DBNotFoundError:
+ break
+ # only delete items in this table
+ if key[:len(table_key)] != table_key:
+ break
+ cur.delete()
+
+ # delete all rowids used by this table
+ table_key = _search_rowid_key(table)
+ while 1:
+ try:
+ key, data = cur.set_range(table_key)
+ except DBNotFoundError:
+ break
+ # only delete items in this table
+ if key[:len(table_key)] != table_key:
+ break
+ cur.delete()
+
+ cur.close()
+
+ # delete the tablename from the table name list
+ tablelist = pickle.loads(
+ self.db.get(_table_names_key, txn=txn, flags=DB_RMW))
+ try:
+ tablelist.remove(table)
+ except ValueError:
+ # hmm, it wasn't there, oh well, that's what we want.
+ pass
+ # delete 1st, incase we opened with DB_DUP
+ self.db.delete(_table_names_key, txn)
+ self.db.put(_table_names_key, pickle.dumps(tablelist, 1), txn=txn)
+
+ txn.commit()
+ txn = None
+
+ if self.__tablecolumns.has_key(table):
+ del self.__tablecolumns[table]
+
+ except DBError, dberror:
+ if txn:
+ txn.abort()
+ raise TableDBError, dberror[1]
--- /dev/null
+++ b/sys/lib/python/bsddb/dbutils.py
@@ -1,0 +1,77 @@
+#------------------------------------------------------------------------
+#
+# Copyright (C) 2000 Autonomous Zone Industries
+#
+# License: This is free software. You may use this software for any
+# purpose including modification/redistribution, so long as
+# this header remains intact and that you do not claim any
+# rights of ownership or authorship of this software. This
+# software has been tested, but no warranty is expressed or
+# implied.
+#
+# Author: Gregory P. Smith <greg@electricrain.com>
+#
+# Note: I don't know how useful this is in reality since when a
+# DBLockDeadlockError happens the current transaction is supposed to be
+# aborted. If it doesn't then when the operation is attempted again
+# the deadlock is still happening...
+# --Robin
+#
+#------------------------------------------------------------------------
+
+
+#
+# import the time.sleep function in a namespace safe way to allow
+# "from bsddb.dbutils import *"
+#
+from time import sleep as _sleep
+
+import db
+
+# always sleep at least N seconds between retrys
+_deadlock_MinSleepTime = 1.0/128
+# never sleep more than N seconds between retrys
+_deadlock_MaxSleepTime = 3.14159
+
+# Assign a file object to this for a "sleeping" message to be written to it
+# each retry
+_deadlock_VerboseFile = None
+
+
+def DeadlockWrap(function, *_args, **_kwargs):
+ """DeadlockWrap(function, *_args, **_kwargs) - automatically retries
+ function in case of a database deadlock.
+
+ This is a function intended to be used to wrap database calls such
+ that they perform retrys with exponentially backing off sleeps in
+ between when a DBLockDeadlockError exception is raised.
+
+ A 'max_retries' parameter may optionally be passed to prevent it
+ from retrying forever (in which case the exception will be reraised).
+
+ d = DB(...)
+ d.open(...)
+ DeadlockWrap(d.put, "foo", data="bar") # set key "foo" to "bar"
+ """
+ sleeptime = _deadlock_MinSleepTime
+ max_retries = _kwargs.get('max_retries', -1)
+ if _kwargs.has_key('max_retries'):
+ del _kwargs['max_retries']
+ while True:
+ try:
+ return function(*_args, **_kwargs)
+ except db.DBLockDeadlockError:
+ if _deadlock_VerboseFile:
+ _deadlock_VerboseFile.write(
+ 'dbutils.DeadlockWrap: sleeping %1.3f\n' % sleeptime)
+ _sleep(sleeptime)
+ # exponential backoff in the sleep time
+ sleeptime *= 2
+ if sleeptime > _deadlock_MaxSleepTime:
+ sleeptime = _deadlock_MaxSleepTime
+ max_retries -= 1
+ if max_retries == -1:
+ raise
+
+
+#------------------------------------------------------------------------
--- /dev/null
+++ b/sys/lib/python/cProfile.py
@@ -1,0 +1,190 @@
+#! /usr/bin/env python
+
+"""Python interface for the 'lsprof' profiler.
+ Compatible with the 'profile' module.
+"""
+
+__all__ = ["run", "runctx", "help", "Profile"]
+
+import _lsprof
+
+# ____________________________________________________________
+# Simple interface
+
+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()
+ result = None
+ try:
+ try:
+ prof = prof.run(statement)
+ except SystemExit:
+ pass
+ finally:
+ if filename is not None:
+ prof.dump_stats(filename)
+ else:
+ result = prof.print_stats(sort)
+ return result
+
+def runctx(statement, globals, locals, filename=None):
+ """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()
+ result = None
+ try:
+ try:
+ prof = prof.runctx(statement, globals, locals)
+ except SystemExit:
+ pass
+ finally:
+ if filename is not None:
+ prof.dump_stats(filename)
+ else:
+ result = prof.print_stats()
+ return result
+
+# Backwards compatibility.
+def help():
+ print "Documentation for the profile/cProfile modules can be found "
+ print "in the Python Library Reference, section 'The Python Profiler'."
+
+# ____________________________________________________________
+
+class Profile(_lsprof.Profiler):
+ """Profile(custom_timer=None, time_unit=None, subcalls=True, builtins=True)
+
+ Builds a profiler object using the specified timer function.
+ The default timer is a fast built-in one based on real time.
+ For custom timer functions returning integers, time_unit can
+ be a float specifying a scale (i.e. how long each integer unit
+ is, in seconds).
+ """
+
+ # Most of the functionality is in the base class.
+ # This subclass only adds convenient and backward-compatible methods.
+
+ def print_stats(self, sort=-1):
+ import pstats
+ pstats.Stats(self).strip_dirs().sort_stats(sort).print_stats()
+
+ def dump_stats(self, file):
+ import marshal
+ f = open(file, 'wb')
+ self.create_stats()
+ marshal.dump(self.stats, f)
+ f.close()
+
+ def create_stats(self):
+ self.disable()
+ self.snapshot_stats()
+
+ def snapshot_stats(self):
+ entries = self.getstats()
+ self.stats = {}
+ callersdicts = {}
+ # call information
+ for entry in entries:
+ func = label(entry.code)
+ nc = entry.callcount # ncalls column of pstats (before '/')
+ cc = nc - entry.reccallcount # ncalls column of pstats (after '/')
+ tt = entry.inlinetime # tottime column of pstats
+ ct = entry.totaltime # cumtime column of pstats
+ callers = {}
+ callersdicts[id(entry.code)] = callers
+ self.stats[func] = cc, nc, tt, ct, callers
+ # subcall information
+ for entry in entries:
+ if entry.calls:
+ func = label(entry.code)
+ for subentry in entry.calls:
+ try:
+ callers = callersdicts[id(subentry.code)]
+ except KeyError:
+ continue
+ nc = subentry.callcount
+ cc = nc - subentry.reccallcount
+ tt = subentry.inlinetime
+ ct = subentry.totaltime
+ if func in callers:
+ prev = callers[func]
+ nc += prev[0]
+ cc += prev[1]
+ tt += prev[2]
+ ct += prev[3]
+ callers[func] = nc, cc, tt, ct
+
+ # 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.enable()
+ try:
+ exec cmd in globals, locals
+ finally:
+ self.disable()
+ return self
+
+ # This method is more useful to profile a single function call.
+ def runcall(self, func, *args, **kw):
+ self.enable()
+ try:
+ return func(*args, **kw)
+ finally:
+ self.disable()
+
+# ____________________________________________________________
+
+def label(code):
+ if isinstance(code, str):
+ return ('~', 0, code) # built-in functions ('~' sorts at the end)
+ else:
+ return (code.co_filename, code.co_firstlineno, code.co_name)
+
+# ____________________________________________________________
+
+def main():
+ import os, sys
+ from optparse import OptionParser
+ usage = "cProfile.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(sys.argv) > 0):
+ sys.path.insert(0, os.path.dirname(sys.argv[0]))
+ run('execfile(%r)' % (sys.argv[0],), 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()
--- /dev/null
+++ b/sys/lib/python/calendar.py
@@ -1,0 +1,701 @@
+"""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)."""
+
+from __future__ import with_statement
+import sys, datetime, 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 xrange(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 xrange(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 1 for leap years, 0 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 xrange(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
+ date += oneday
+ 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 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
+ 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 xrange(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 xrange(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 xrange(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 xrange(January, January+12)
+ ]
+ return [months[i:i+width] for i in xrange(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 xrange(January, January+12)
+ ]
+ return [months[i:i+width] for i in xrange(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 xrange(January, January+12)
+ ]
+ return [months[i:i+width] for i in xrange(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.week(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 = xrange(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 xrange(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"> </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 xrange(January, January+12, width):
+ # months in this row
+ months = xrange(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.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):
+ 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)
+
+ if options.type == "html":
+ if options.locale:
+ cal = LocaleHTMLCalendar(locale=options.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=options.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)
--- /dev/null
+++ b/sys/lib/python/cgi.py
@@ -1,0 +1,1071 @@
+#! /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 urllib
+import mimetools
+import rfc822
+import UserDict
+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
+ URL 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 parse_qs(qs, keep_blank_values, strict_parsing)
+
+
+def parse_qs(qs, keep_blank_values=0, strict_parsing=0):
+ """Parse a query given as a string argument.
+
+ Arguments:
+
+ qs: URL-encoded query string to be parsed
+
+ keep_blank_values: flag indicating whether blank values in
+ URL 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: URL-encoded query string to be parsed
+
+ keep_blank_values: flag indicating whether blank values in
+ URL 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 = urllib.unquote(nv[0].replace('+', ' '))
+ value = urllib.unquote(nv[1].replace('+', ' '))
+ r.append((name, value))
+
+ return r
+
+
+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 parse_header(line):
+ """Parse a Content-type like header.
+
+ Return the main content-type and a dictionary of options.
+
+ """
+ plist = [x.strip() for x in line.split(';')]
+ key = plist.pop(0).lower()
+ pdict = {}
+ for p in plist:
+ 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
+ URL 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()
+ 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 '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"
+ keys = []
+ for item in self.list:
+ if item.name not in keys: keys.append(item.name)
+ return keys
+
+ def has_key(self, key):
+ """Dictionary style has_key() method."""
+ if self.list is None:
+ raise TypeError, "not indexable"
+ for item in self.list:
+ if item.name == key: return True
+ return False
+
+ def __contains__(self, key):
+ """Dictionary style __contains__ method."""
+ if self.list is None:
+ raise TypeError, "not indexable"
+ for item in self.list:
+ if item.name == key: return True
+ return False
+
+ def __len__(self):
+ """Dictionary style len(x) support."""
+ return len(self.keys())
+
+ def read_urlencoded(self):
+ """Internal: read data in query string format."""
+ qs = self.fp.read(self.length)
+ self.list = list = []
+ for key, value in 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 = []
+ 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):
+ self.dict = self.data = parse(environ=environ)
+ 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"
+ 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 "<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 "<H3>Shell Environment:</H3>"
+ print "<DL>"
+ for key in keys:
+ print "<DT>", escape(key), "<DD>", escape(environ[key])
+ print "</DL>"
+
+def print_form(form):
+ """Dump the contents of a form as HTML."""
+ keys = form.keys()
+ keys.sort()
+ 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>"
+
+def print_directory():
+ """Dump the current directory as HTML."""
+ print "<H3>Current Working Directory:</H3>"
+ try:
+ pwd = os.getcwd()
+ except os.error, msg:
+ print "os.error:", escape(str(msg))
+ else:
+ print escape(pwd)
+
+def print_arguments():
+ print "<H3>Command Line Arguments:</H3>"
+ print sys.argv
+
+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("&", "&") # Must be done first!
+ s = s.replace("<", "<")
+ s = s.replace(">", ">")
+ if quote:
+ s = s.replace('"', """)
+ 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()
--- /dev/null
+++ b/sys/lib/python/cgitb.py
@@ -1,0 +1,317 @@
+"""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.
+"""
+
+__author__ = 'Ka-Ping Yee'
+
+__version__ = '$Revision: 39758 $'
+
+import sys
+
+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."""
+ import tokenize, keyword
+ 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((etype, evalue, etb), context=5):
+ """Return a nice HTML document describing a given traceback."""
+ import os, types, time, traceback, linecache, inspect, pydoc
+
+ 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(' ' * 5) + ' </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> </big>', link, call)]
+ if index is not None:
+ i = lnum - index
+ for line in lines:
+ num = small(' ' * (5-len(str(i))) + str(i)) + ' '
+ line = '<tt>%s%s</tt>' % (num, pydoc.html.preformat(line))
+ if i in highlight:
+ rows.append('<tr><td bgcolor="#ffccee">%s</td></tr>' % line)
+ else:
+ 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 = %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 type(evalue) is types.InstanceType:
+ for name in dir(evalue):
+ if name[:1] == '_': continue
+ value = pydoc.html.repr(getattr(evalue, name))
+ exception.append('\n<br>%s%s =\n%s' % (indent, name, value))
+
+ import traceback
+ 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
+-->
+''' % ''.join(traceback.format_exception(etype, evalue, etb))
+
+def text((etype, evalue, etb), context=5):
+ """Return a plain text document describing a given traceback."""
+ import os, types, time, traceback, linecache, inspect, pydoc
+
+ 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 type(evalue) is types.InstanceType:
+ for name in dir(evalue):
+ value = pydoc.text.repr(getattr(evalue, name))
+ exception.append('\n%s%s = %s' % (" "*4, name, value))
+
+ import traceback
+ 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
+ import traceback
+ doc = ''.join(traceback.format_exception(*info))
+ plain = True
+
+ if self.display:
+ if plain:
+ doc = doc.replace('&', '&').replace('<', '<')
+ 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:
+ import os, tempfile
+ 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 = '<p> %s contains the description of this error.' % path
+ except:
+ msg = '<p> Tried to save traceback to %s, but failed.' % path
+ 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)
--- /dev/null
+++ b/sys/lib/python/chunk.py
@@ -1,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
--- /dev/null
+++ b/sys/lib/python/cmd.py
@@ -1,0 +1,405 @@
+"""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[:-1] # chop \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 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):
+ # Inheritance says we have to look in class and
+ # base classes; order is not important.
+ names = []
+ classes = [self.__class__]
+ while classes:
+ aclass = classes.pop(0)
+ if aclass.__bases__:
+ classes = classes + list(aclass.__bases__)
+ names = names + dir(aclass)
+ return names
+
+ def complete_help(self, *args):
+ return self.completenames(*args)
+
+ def do_help(self, arg):
+ 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)))
--- /dev/null
+++ b/sys/lib/python/code.py
@@ -1,0 +1,307 @@
+"""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):
+
+ 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)
+ 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__':
+ import pdb
+ pdb.run("interact()\n")
--- /dev/null
+++ b/sys/lib/python/codecs.py
@@ -1,0 +1,1034 @@
+""" 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.
+ """
+
+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 = ""
+
+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.
+ """
+
+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 = ""
+
+#
+# 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 __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.reset()
+ self.stream.seek(offset, whence)
+
+ 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 __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 and \
+ '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')
--- /dev/null
+++ b/sys/lib/python/codeop.py
@@ -1,0 +1,168 @@
+r"""Utilities to compile possibly incomplete Python source code.
+
+This module provides two interfaces, broadly similar to the builtin
+function compile(), which take program text, a filename and a 'mode'
+and:
+
+- Return 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 __future__
+
+_features = [getattr(__future__, fname)
+ for fname in __future__.all_feature_names]
+
+__all__ = ["compile_command", "Compile", "CommandCompiler"]
+
+PyCF_DONT_IMPLY_DEDENT = 0x200 # Matches pythonrun.h
+
+def _maybe_compile(compiler, source, filename, symbol):
+ # Check for source consisting of only blank lines and comments
+ for line in source.split("\n"):
+ line = line.strip()
+ if line and line[0] != '#':
+ break # Leave it alone
+ else:
+ if symbol != "eval":
+ source = "pass" # Replace it with a 'pass' statement
+
+ err = err1 = err2 = None
+ code = code1 = code2 = None
+
+ try:
+ code = compiler(source, filename, symbol)
+ except SyntaxError, err:
+ pass
+
+ try:
+ code1 = compiler(source + "\n", filename, symbol)
+ except SyntaxError, err1:
+ pass
+
+ try:
+ code2 = compiler(source + "\n\n", filename, symbol)
+ except SyntaxError, err2:
+ pass
+
+ if code:
+ return code
+ if not code1 and repr(err1) == repr(err2):
+ raise SyntaxError, err1
+
+def _compile(source, filename, symbol):
+ return compile(source, filename, symbol, PyCF_DONT_IMPLY_DEDENT)
+
+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).
+ """
+ return _maybe_compile(_compile, source, filename, symbol)
+
+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.flags = PyCF_DONT_IMPLY_DEDENT
+
+ def __call__(self, source, filename, symbol):
+ codeob = compile(source, filename, symbol, self.flags, 1)
+ for feature in _features:
+ if codeob.co_flags & feature.compiler_flag:
+ self.flags |= feature.compiler_flag
+ return codeob
+
+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.compiler = Compile()
+
+ 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).
+ """
+ return _maybe_compile(self.compiler, source, filename, symbol)
--- /dev/null
+++ b/sys/lib/python/colorsys.py
@@ -1,0 +1,126 @@
+"""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))
+ if i%6 == 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
--- /dev/null
+++ b/sys/lib/python/commands.py
@@ -1,0 +1,84 @@
+"""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.]
+"""
+
+__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."""
+ 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
--- /dev/null
+++ b/sys/lib/python/compileall.py
@@ -1,0 +1,157 @@
+"""Module/script to "compile" all .py files to .pyc (or .pyo) file.
+
+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
+
+__all__ = ["compile_dir","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: if given, purported directory name (this is the
+ directory name that will show up in error messages)
+ 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 rx is not None:
+ mo = rx.search(fullname)
+ if mo:
+ continue
+ if os.path.isfile(fullname):
+ head, tail = name[:-3], name[-3:]
+ if tail == '.py':
+ cfile = fullname + (__debug__ and 'c' or 'o')
+ ftime = os.stat(fullname).st_mtime
+ try: ctime = os.stat(cfile).st_mtime
+ except os.error: ctime = 0
+ if (ctime > ftime) and not force: continue
+ if not quiet:
+ print 'Compiling', fullname, '...'
+ try:
+ ok = py_compile.compile(fullname, None, dfile, True)
+ except KeyboardInterrupt:
+ raise KeyboardInterrupt
+ 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
+ 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_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 main():
+ """Script main program."""
+ import getopt
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], 'lfqd:x:')
+ except getopt.error, msg:
+ print msg
+ print "usage: python compileall.py [-l] [-f] [-q] [-d destdir] " \
+ "[-x regexp] [directory ...]"
+ print "-l: don't recurse down"
+ print "-f: force rebuild even if timestamps are up-to-date"
+ print "-q: quiet operation"
+ print "-d destdir: purported directory name for error messages"
+ print " if no directory arguments, -l sys.path is assumed"
+ print "-x regexp: skip files matching the regular expression regexp"
+ print " the regexp is search for in the full path of the file"
+ sys.exit(2)
+ maxlevels = 10
+ ddir = None
+ force = 0
+ quiet = 0
+ rx = 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 ddir:
+ if len(args) != 1:
+ print "-d destdir require exactly one directory argument"
+ sys.exit(2)
+ success = 1
+ try:
+ if args:
+ for dir in args:
+ if not compile_dir(dir, maxlevels, ddir,
+ force, rx, quiet):
+ success = 0
+ else:
+ success = compile_path()
+ except KeyboardInterrupt:
+ print "\n[interrupt]"
+ success = 0
+ return success
+
+if __name__ == '__main__':
+ exit_status = int(not main())
+ sys.exit(exit_status)
--- /dev/null
+++ b/sys/lib/python/compiler/__init__.py
@@ -1,0 +1,26 @@
+"""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.
+"""
+
+from compiler.transformer import parse, parseFile
+from compiler.visitor import walk
+from compiler.pycodegen import compile, compileFile
--- /dev/null
+++ b/sys/lib/python/compiler/ast.py
@@ -1,0 +1,1356 @@
+"""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, (left, right), lineno=None):
+ self.left = left
+ self.right = right
+ 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, lineno=None):
+ self.name = name
+ self.bases = bases
+ self.doc = doc
+ self.code = code
+ self.lineno = lineno
+
+ def getChildren(self):
+ children = []
+ children.append(self.name)
+ children.extend(flatten(self.bases))
+ children.append(self.doc)
+ children.append(self.code)
+ return tuple(children)
+
+ def getChildNodes(self):
+ nodelist = []
+ nodelist.extend(flatten_nodes(self.bases))
+ nodelist.append(self.code)
+ return tuple(nodelist)
+
+ def __repr__(self):
+ return "Class(%s, %s, %s, %s)" % (repr(self.name), repr(self.bases), repr(self.doc), repr(self.code))
+
+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, (left, right), lineno=None):
+ self.left = left
+ self.right = right
+ 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, (left, right), lineno=None):
+ self.left = left
+ self.right = right
+ 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, (left, right), lineno=None):
+ self.left = left
+ self.right = right
+ 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 Mod(Node):
+ def __init__(self, (left, right), lineno=None):
+ self.left = left
+ self.right = right
+ 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, (left, right), lineno=None):
+ self.left = left
+ self.right = right
+ 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, (left, right), lineno=None):
+ self.left = left
+ self.right = right
+ 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, (left, right), lineno=None):
+ self.left = left
+ self.right = right
+ 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 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, (left, right), lineno=None):
+ self.left = left
+ self.right = right
+ 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
--- /dev/null
+++ b/sys/lib/python/compiler/consts.py
@@ -1,0 +1,21 @@
+# operation flags
+OP_ASSIGN = 'OP_ASSIGN'
+OP_DELETE = 'OP_DELETE'
+OP_APPLY = 'OP_APPLY'
+
+SC_LOCAL = 1
+SC_GLOBAL = 2
+SC_FREE = 3
+SC_CELL = 4
+SC_UNKNOWN = 5
+
+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
--- /dev/null
+++ b/sys/lib/python/compiler/future.py
@@ -1,0 +1,73 @@
+"""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")
+
+ 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
--- /dev/null
+++ b/sys/lib/python/compiler/misc.py
@@ -1,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 self.elts.has_key(elt)
+ def add(self, elt):
+ self.elts[elt] = elt
+ def elements(self):
+ return self.elts.keys()
+ def has_elt(self, elt):
+ return self.elts.has_key(elt)
+ 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())
--- /dev/null
+++ b/sys/lib/python/compiler/pyassem.py
@@ -1,0 +1,818 @@
+"""A flow graph representation for Python bytecode"""
+
+import dis
+import new
+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 " ", 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 incorrect to add an implicit
+ # transfer to the block graph. The current code requires
+ # these edges to get the blocks emitted in the right order,
+ # however. :-( If a client needs to remove these edges, call
+ # pruneEdges().
+
+ 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 inst[0] in ['RETURN_VALUE', 'YIELD_VALUE']:
+ self.current.addOutEdge(self.exit)
+ 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
+ """
+ # XXX make sure every node that doesn't have an explicit next
+ # is set so that next points to exit
+ for b in self.blocks.elements():
+ if b is self.exit:
+ continue
+ if not b.next:
+ b.addNext(self.exit)
+ order = dfs_postorder(self.entry, {})
+ order.reverse()
+ self.fixupOrder(order, self.exit)
+ # hack alert
+ if not self.exit in order:
+ order.append(self.exit)
+
+ return order
+
+ def fixupOrder(self, blocks, default_next):
+ """Fixup bad order introduced by DFS."""
+
+ # XXX This is a total mess. There must be a better way to get
+ # the code blocks in the right order.
+
+ self.fixupOrderHonorNext(blocks, default_next)
+ self.fixupOrderForward(blocks, default_next)
+
+ def fixupOrderHonorNext(self, blocks, default_next):
+ """Fix one problem with DFS.
+
+ The DFS uses child block, but doesn't know about the special
+ "next" block. As a result, the DFS can order blocks so that a
+ block isn't next to the right block for implicit control
+ transfers.
+ """
+ index = {}
+ for i in range(len(blocks)):
+ index[blocks[i]] = i
+
+ for i in range(0, len(blocks) - 1):
+ b = blocks[i]
+ n = blocks[i + 1]
+ if not b.next or b.next[0] == default_next or b.next[0] == n:
+ continue
+ # The blocks are in the wrong order. Find the chain of
+ # blocks to insert where they belong.
+ cur = b
+ chain = []
+ elt = cur
+ while elt.next and elt.next[0] != default_next:
+ chain.append(elt.next[0])
+ elt = elt.next[0]
+ # Now remove the blocks in the chain from the current
+ # block list, so that they can be re-inserted.
+ l = []
+ for b in chain:
+ assert index[b] > i
+ l.append((index[b], b))
+ l.sort()
+ l.reverse()
+ for j, b in l:
+ del blocks[index[b]]
+ # Insert the chain in the proper location
+ blocks[i:i + 1] = [cur] + chain
+ # Finally, re-compute the block indexes
+ for i in range(len(blocks)):
+ index[blocks[i]] = i
+
+ def fixupOrderForward(self, blocks, default_next):
+ """Make sure all JUMP_FORWARDs jump forward"""
+ index = {}
+ chains = []
+ cur = []
+ for b in blocks:
+ index[b] = len(chains)
+ cur.append(b)
+ if b.next and b.next[0] == default_next:
+ chains.append(cur)
+ cur = []
+ chains.append(cur)
+
+ while 1:
+ constraints = []
+
+ for i in range(len(chains)):
+ l = chains[i]
+ for b in l:
+ for c in b.get_children():
+ if index[c] < i:
+ forward_p = 0
+ for inst in b.insts:
+ if inst[0] == 'JUMP_FORWARD':
+ if inst[1] == c:
+ forward_p = 1
+ if not forward_p:
+ continue
+ constraints.append((index[c], i))
+
+ if not constraints:
+ break
+
+ # XXX just do one for now
+ # do swaps to get things in the right order
+ goes_before, a_chain = constraints[0]
+ assert a_chain > goes_before
+ c = chains[a_chain]
+ chains.remove(c)
+ chains.insert(goes_before, c)
+
+ del blocks[:]
+ for c in chains:
+ for b in c:
+ blocks.append(b)
+
+ 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 dfs_postorder(b, seen):
+ """Depth-first search of tree rooted at b, return in postorder"""
+ order = []
+ seen[b] = b
+ for c in b.get_children():
+ if seen.has_key(c):
+ continue
+ order = order + dfs_postorder(c, seen)
+ order.append(b)
+ return order
+
+class Block:
+ _count = 0
+
+ def __init__(self, label=''):
+ self.insts = []
+ self.inEdges = misc.Set()
+ self.outEdges = misc.Set()
+ self.label = label
+ self.bid = Block._count
+ self.next = []
+ 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]
+ if op[:4] == 'JUMP':
+ self.outEdges.add(inst[1])
+ self.insts.append(inst)
+
+ def getInstructions(self):
+ return self.insts
+
+ def addInEdge(self, block):
+ self.inEdges.add(block)
+
+ 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)
+
+ _uncond_transfer = ('RETURN_VALUE', 'RAISE_VARARGS', 'YIELD_VALUE',
+ 'JUMP_ABSOLUTE', 'JUMP_FORWARD', 'CONTINUE_LOOP')
+
+ def pruneNext(self):
+ """Remove bogus edge for unconditional transfers
+
+ Each block has a next edge that accounts for implicit control
+ transfers, e.g. from a JUMP_IF_FALSE to the block that will be
+ executed if the test is true.
+
+ These edges must remain for the current assembler code to
+ work. If they are removed, the dfs_postorder gets things in
+ weird orders. However, they shouldn't be there for other
+ purposes, e.g. conversion to SSA form. This method will
+ remove the next edge when it follows an unconditional control
+ transfer.
+ """
+ try:
+ op, arg = self.insts[-1]
+ except (IndexError, ValueError):
+ return
+ if op in self._uncond_transfer:
+ self.next = []
+
+ def get_children(self):
+ if self.next and self.next[0] in self.outEdges:
+ self.outEdges.remove(self.next[0])
+ return self.outEdges.elements() + self.next
+
+ 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":
+ 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 seen.has_key(b):
+ 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 self.hasjrel.has_elt(opname):
+ oparg = inst[1]
+ offset = begin[oparg] - pc
+ insts[i] = opname, offset
+ elif self.hasjabs.has_elt(opname):
+ insts[i] = opname, begin[inst[1]]
+ self.stage = FLAT
+
+ hasjrel = misc.Set()
+ for i in dis.hasjrel:
+ hasjrel.add(dis.opname[i])
+ hasjabs = misc.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 cells.has_key(name)]
+ 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 new.code(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': -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 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
--- /dev/null
+++ b/sys/lib/python/compiler/pycodegen.py
@@ -1,0 +1,1533 @@
+import imp
+import os
+import marshal
+import struct
+import sys
+from cStringIO import StringIO
+
+from compiler import ast, parse, walk, syntax
+from compiler import pyassem, misc, future, symbols
+from compiler.consts import SC_LOCAL, SC_GLOBAL, 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)
+from compiler.pyassem import TupleArg
+
+# 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()
+
+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 = 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)
+
+ 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:
+ 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)
--- /dev/null
+++ b/sys/lib/python/compiler/symbols.py
@@ -1,0 +1,463 @@
+"""Module symbol-table generator"""
+
+from compiler import ast
+from compiler.consts import SC_LOCAL, SC_GLOBAL, 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 self.uses.has_key(name) or self.defs.has_key(name):
+ pass # XXX warn about global following def/use
+ if self.params.has_key(name):
+ 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 self.globals.has_key(name):
+ return SC_GLOBAL
+ if self.cells.has_key(name):
+ return SC_CELL
+ if self.defs.has_key(name):
+ return SC_LOCAL
+ if self.nested and (self.frees.has_key(name) or
+ self.uses.has_key(name)):
+ return SC_FREE
+ if self.nested:
+ return SC_UNKNOWN
+ else:
+ return SC_GLOBAL
+
+ def get_free_vars(self):
+ if not self.nested:
+ return ()
+ free = {}
+ free.update(self.frees)
+ for name in self.uses.keys():
+ if not (self.defs.has_key(name) or
+ self.globals.has_key(name)):
+ 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 self.frees.has_key(name):
+ 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:
+ 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 "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)
--- /dev/null
+++ b/sys/lib/python/compiler/syntax.py
@@ -1,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")
--- /dev/null
+++ b/sys/lib/python/compiler/transformer.py
@@ -1,0 +1,1490 @@
+"""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 parser
+import symbol
+import token
+import sys
+
+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
--- /dev/null
+++ b/sys/lib/python/compiler/visitor.py
@@ -1,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 not self.examples.has_key(klass):
+ self.examples[klass] = klass
+ print self.visitor
+ print klass
+ for attr in dir(node):
+ if attr[0] != '_':
+ print "\t", "%-12.12s" % attr, getattr(node, attr)
+ 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)
--- /dev/null
+++ b/sys/lib/python/config/Makefile
@@ -1,0 +1,1088 @@
+# Top-level Makefile for Python
+#
+# As distributed, this file is called Makefile.pre.in; it is processed
+# into the real Makefile by running the script ./configure, which
+# replaces things like @spam@ with values appropriate for your system.
+# This means that if you edit Makefile, your changes get lost the next
+# time you run the configure script. Ideally, you can do:
+#
+# ./configure
+# make
+# make test
+# make install
+#
+# If you have a previous version of Python installed that you don't
+# want to overwrite, you can use "make altinstall" instead of "make
+# install". Refer to the "Installing" section in the README file for
+# additional details.
+#
+# See also the section "Build instructions" in the README file.
+
+# === Variables set by makesetup ===
+
+MODOBJS= _MODOBJS_
+MODLIBS= _MODLIBS_
+
+# === Variables set by configure
+VERSION= @VERSION@
+srcdir= @srcdir@
+VPATH= @srcdir@
+
+CC= @CC@
+CXX= @CXX@
+MAINCC= @MAINCC@
+LINKCC= @LINKCC@
+AR= @AR@
+RANLIB= @RANLIB@
+SVNVERSION= @SVNVERSION@
+
+# Shell used by make (some versions default to the login shell, which is bad)
+SHELL= /bin/sh
+
+# Use this to make a link between python$(VERSION) and python in $(BINDIR)
+LN= @LN@
+
+# Portable install script (configure doesn't always guess right)
+INSTALL= @INSTALL@
+INSTALL_PROGRAM=@INSTALL_PROGRAM@
+INSTALL_SCRIPT= @INSTALL_SCRIPT@
+INSTALL_DATA= @INSTALL_DATA@
+# Shared libraries must be installed with executable mode on some systems;
+# rather than figuring out exactly which, we always give them executable mode.
+# Also, making them read-only seems to be a good idea...
+INSTALL_SHARED= ${INSTALL} -m 555
+
+MAKESETUP= $(srcdir)/Modules/makesetup
+
+# Compiler options
+OPT= @OPT@
+BASECFLAGS= @BASECFLAGS@
+CFLAGS= $(BASECFLAGS) $(OPT) $(EXTRA_CFLAGS)
+# Both CPPFLAGS and LDFLAGS need to contain the shell's value for setup.py to
+# be able to build extension modules using the directories specified in the
+# environment variables
+CPPFLAGS= -I. -I$(srcdir)/Include @CPPFLAGS@
+LDFLAGS= @LDFLAGS@
+LDLAST= @LDLAST@
+SGI_ABI= @SGI_ABI@
+CCSHARED= @CCSHARED@
+LINKFORSHARED= @LINKFORSHARED@
+# Extra C flags added for building the interpreter object files.
+CFLAGSFORSHARED=@CFLAGSFORSHARED@
+# C flags used for building the interpreter object files
+PY_CFLAGS= $(CFLAGS) $(CPPFLAGS) $(CFLAGSFORSHARED) -DPy_BUILD_CORE
+
+
+# Machine-dependent subdirectories
+MACHDEP= @MACHDEP@
+
+# Install prefix for architecture-independent files
+prefix= @prefix@
+
+# Install prefix for architecture-dependent files
+exec_prefix= @exec_prefix@
+
+# Expanded directories
+BINDIR= $(exec_prefix)/bin
+LIBDIR= $(exec_prefix)/lib
+MANDIR= @mandir@
+INCLUDEDIR= @includedir@
+CONFINCLUDEDIR= $(exec_prefix)/include
+SCRIPTDIR= $(prefix)/lib
+
+# Detailed destination directories
+BINLIBDEST= $(LIBDIR)/python$(VERSION)
+LIBDEST= $(SCRIPTDIR)/python$(VERSION)
+INCLUDEPY= $(INCLUDEDIR)/python$(VERSION)
+CONFINCLUDEPY= $(CONFINCLUDEDIR)/python$(VERSION)
+LIBP= $(LIBDIR)/python$(VERSION)
+
+# Symbols used for using shared libraries
+SO= @SO@
+LDSHARED= @LDSHARED@
+BLDSHARED= @BLDSHARED@
+DESTSHARED= $(BINLIBDEST)/lib-dynload
+
+# Executable suffix (.exe on Windows and Mac OS X)
+EXE= @EXEEXT@
+BUILDEXE= @BUILDEXEEXT@
+
+# Short name and location for Mac OS X Python framework
+UNIVERSALSDK=@UNIVERSALSDK@
+PYTHONFRAMEWORK= @PYTHONFRAMEWORK@
+PYTHONFRAMEWORKDIR= @PYTHONFRAMEWORKDIR@
+PYTHONFRAMEWORKPREFIX= @PYTHONFRAMEWORKPREFIX@
+PYTHONFRAMEWORKINSTALLDIR= @PYTHONFRAMEWORKINSTALLDIR@
+# Deployment target selected during configure, to be checked
+# by distutils. The export statement is needed to ensure that the
+# deployment target is active during build.
+MACOSX_DEPLOYMENT_TARGET=@CONFIGURE_MACOSX_DEPLOYMENT_TARGET@
+@EXPORT_MACOSX_DEPLOYMENT_TARGET@export MACOSX_DEPLOYMENT_TARGET
+
+# Options to enable prebinding (for fast startup prior to Mac OS X 10.3)
+OTHER_LIBTOOL_OPT=@OTHER_LIBTOOL_OPT@
+
+# Environment to run shared python without installed libraries
+RUNSHARED= @RUNSHARED@
+
+# Modes for directories, executables and data files created by the
+# install process. Default to user-only-writable for all file types.
+DIRMODE= 755
+EXEMODE= 755
+FILEMODE= 644
+
+# configure script arguments
+CONFIG_ARGS= @CONFIG_ARGS@
+
+
+# Subdirectories with code
+SRCDIRS= @SRCDIRS@
+
+# Other subdirectories
+SUBDIRSTOO= Include Lib Misc Demo
+
+# Files and directories to be distributed
+CONFIGFILES= configure configure.in acconfig.h pyconfig.h.in Makefile.pre.in
+DISTFILES= README ChangeLog $(CONFIGFILES)
+DISTDIRS= $(SUBDIRS) $(SUBDIRSTOO) Ext-dummy
+DIST= $(DISTFILES) $(DISTDIRS)
+
+
+LIBRARY= @LIBRARY@
+LDLIBRARY= @LDLIBRARY@
+BLDLIBRARY= @BLDLIBRARY@
+DLLLIBRARY= @DLLLIBRARY@
+LDLIBRARYDIR= @LDLIBRARYDIR@
+INSTSONAME= @INSTSONAME@
+
+
+LIBS= @LIBS@
+LIBM= @LIBM@
+LIBC= @LIBC@
+SYSLIBS= $(LIBM) $(LIBC)
+SHLIBS= @SHLIBS@
+
+THREADOBJ= @THREADOBJ@
+DLINCLDIR= @DLINCLDIR@
+DYNLOADFILE= @DYNLOADFILE@
+MACHDEP_OBJS= @MACHDEP_OBJS@
+UNICODE_OBJS= @UNICODE_OBJS@
+
+PYTHON= python$(EXE)
+BUILDPYTHON= python$(BUILDEXE)
+
+# === Definitions added by makesetup ===
+
+
+##########################################################################
+# Modules
+MODULE_OBJS= \
+ Modules/config.o \
+ Modules/getpath.o \
+ Modules/main.o \
+ Modules/gcmodule.o
+
+# Used of signalmodule.o is not available
+SIGNAL_OBJS= @SIGNAL_OBJS@
+
+
+##########################################################################
+# Grammar
+GRAMMAR_H= $(srcdir)/Include/graminit.h
+GRAMMAR_C= $(srcdir)/Python/graminit.c
+GRAMMAR_INPUT= $(srcdir)/Grammar/Grammar
+
+
+##########################################################################
+# Parser
+PGEN= Parser/pgen$(EXE)
+
+POBJS= \
+ Parser/acceler.o \
+ Parser/grammar1.o \
+ Parser/listnode.o \
+ Parser/node.o \
+ Parser/parser.o \
+ Parser/parsetok.o \
+ Parser/bitset.o \
+ Parser/metagrammar.o \
+ Parser/firstsets.o \
+ Parser/grammar.o \
+ Parser/pgen.o
+
+PARSER_OBJS= $(POBJS) Parser/myreadline.o Parser/tokenizer.o
+
+PGOBJS= \
+ Objects/obmalloc.o \
+ Python/mysnprintf.o \
+ Parser/tokenizer_pgen.o \
+ Parser/printgrammar.o \
+ Parser/pgenmain.o
+
+PGENOBJS= $(PGENMAIN) $(POBJS) $(PGOBJS)
+
+##########################################################################
+# AST
+AST_H_DIR= $(srcdir)/Include
+AST_H= $(AST_H_DIR)/Python-ast.h
+AST_C_DIR= $(srcdir)/Python
+AST_C= $(AST_C_DIR)/Python-ast.c
+AST_ASDL= $(srcdir)/Parser/Python.asdl
+
+ASDLGEN_FILES= $(srcdir)/Parser/asdl.py $(srcdir)/Parser/asdl_c.py
+# XXX Note that a build now requires Python exist before the build starts
+ASDLGEN= $(srcdir)/Parser/asdl_c.py
+
+##########################################################################
+# Python
+PYTHON_OBJS= \
+ Python/Python-ast.o \
+ Python/asdl.o \
+ Python/ast.o \
+ Python/bltinmodule.o \
+ Python/ceval.o \
+ Python/compile.o \
+ Python/codecs.o \
+ Python/errors.o \
+ Python/frozen.o \
+ Python/frozenmain.o \
+ Python/future.o \
+ Python/getargs.o \
+ Python/getcompiler.o \
+ Python/getcopyright.o \
+ Python/getmtime.o \
+ Python/getplatform.o \
+ Python/getversion.o \
+ Python/graminit.o \
+ Python/import.o \
+ Python/importdl.o \
+ Python/marshal.o \
+ Python/modsupport.o \
+ Python/mystrtoul.o \
+ Python/mysnprintf.o \
+ Python/pyarena.o \
+ Python/pyfpe.o \
+ Python/pystate.o \
+ Python/pythonrun.o \
+ Python/structmember.o \
+ Python/symtable.o \
+ Python/sysmodule.o \
+ Python/traceback.o \
+ Python/getopt.o \
+ Python/pystrtod.o \
+ Python/$(DYNLOADFILE) \
+ $(MACHDEP_OBJS) \
+ $(THREADOBJ)
+
+
+##########################################################################
+# Objects
+OBJECT_OBJS= \
+ Objects/abstract.o \
+ Objects/boolobject.o \
+ Objects/bufferobject.o \
+ Objects/cellobject.o \
+ Objects/classobject.o \
+ Objects/cobject.o \
+ Objects/codeobject.o \
+ Objects/complexobject.o \
+ Objects/descrobject.o \
+ Objects/enumobject.o \
+ Objects/exceptions.o \
+ Objects/genobject.o \
+ Objects/fileobject.o \
+ Objects/floatobject.o \
+ Objects/frameobject.o \
+ Objects/funcobject.o \
+ Objects/intobject.o \
+ Objects/iterobject.o \
+ Objects/listobject.o \
+ Objects/longobject.o \
+ Objects/dictobject.o \
+ Objects/methodobject.o \
+ Objects/moduleobject.o \
+ Objects/object.o \
+ Objects/obmalloc.o \
+ Objects/rangeobject.o \
+ Objects/setobject.o \
+ Objects/sliceobject.o \
+ Objects/stringobject.o \
+ Objects/structseq.o \
+ Objects/tupleobject.o \
+ Objects/typeobject.o \
+ Objects/weakrefobject.o \
+ $(UNICODE_OBJS)
+
+
+##########################################################################
+# objects that get linked into the Python library
+LIBRARY_OBJS= \
+ Modules/_typesmodule.o \
+ Modules/getbuildinfo.o \
+ $(PARSER_OBJS) \
+ $(OBJECT_OBJS) \
+ $(PYTHON_OBJS) \
+ $(MODULE_OBJS) \
+ $(SIGNAL_OBJS) \
+ $(MODOBJS)
+
+#########################################################################
+# Rules
+
+# Default target
+all: $(BUILDPYTHON) oldsharedmods sharedmods
+
+# Build the interpreter
+$(BUILDPYTHON): Modules/python.o $(LIBRARY) $(LDLIBRARY)
+ $(LINKCC) $(LDFLAGS) $(LINKFORSHARED) -o $@ \
+ Modules/python.o \
+ $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST)
+
+platform: $(BUILDPYTHON)
+ $(RUNSHARED) ./$(BUILDPYTHON) -E -c 'import sys ; from distutils.util import get_platform ; print get_platform()+"-"+sys.version[0:3]' >platform
+
+
+# Build the shared modules
+sharedmods: $(BUILDPYTHON)
+ case $$MAKEFLAGS in \
+ *-s*) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' ./$(BUILDPYTHON) -E $(srcdir)/setup.py -q build;; \
+ *) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' ./$(BUILDPYTHON) -E $(srcdir)/setup.py build;; \
+ esac
+
+# Build static library
+# avoid long command lines, same as LIBRARY_OBJS
+$(LIBRARY): $(LIBRARY_OBJS)
+ -rm -f $@
+ $(AR) cr $@ Modules/getbuildinfo.o
+ $(AR) cr $@ Modules/_typesmodule.o
+ $(AR) cr $@ $(PARSER_OBJS)
+ $(AR) cr $@ $(OBJECT_OBJS)
+ $(AR) cr $@ $(PYTHON_OBJS)
+ $(AR) cr $@ $(MODULE_OBJS) $(SIGNAL_OBJS)
+ $(AR) cr $@ $(MODOBJS)
+ $(RANLIB) $@
+
+libpython$(VERSION).so: $(LIBRARY_OBJS)
+ if test $(INSTSONAME) != $(LDLIBRARY); then \
+ $(LDSHARED) -Wl,-h$(INSTSONAME) -o $(INSTSONAME) $(LIBRARY_OBJS) $(SHLIBS) $(LIBC) $(LIBM); \
+ $(LN) -f $(INSTSONAME) $@; \
+ else\
+ $(LDSHARED) -o $@ $(LIBRARY_OBJS) $(SHLIBS) $(LIBC) $(LIBM); \
+ fi
+
+libpython$(VERSION).sl: $(LIBRARY_OBJS)
+ $(LDSHARED) -o $@ $(LIBRARY_OBJS) $(SHLIBS) $(LIBC) $(LIBM)
+
+# This rule is here for OPENSTEP/Rhapsody/MacOSX. It builds a temporary
+# minimal framework (not including the Lib directory and such) in the current
+# directory.
+RESSRCDIR=$(srcdir)/Mac/Resources/framework
+$(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK): \
+ $(LIBRARY) \
+ $(RESSRCDIR)/Info.plist \
+ $(RESSRCDIR)/version.plist \
+ $(RESSRCDIR)/English.lproj/InfoPlist.strings
+ $(INSTALL) -d -m $(DIRMODE) $(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)
+ if test "${UNIVERSALSDK}"; then \
+ $(CC) -o $(LDLIBRARY) -arch i386 -arch ppc -dynamiclib \
+ -isysroot "${UNIVERSALSDK}" \
+ -all_load $(LIBRARY) -Wl,-single_module \
+ -install_name $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Versions/$(VERSION)/Python \
+ -compatibility_version $(VERSION) \
+ -current_version $(VERSION); \
+ else \
+ libtool -o $(LDLIBRARY) -dynamic $(OTHER_LIBTOOL_OPT) $(LIBRARY) \
+ @LIBTOOL_CRUFT@ ;\
+ fi
+ $(INSTALL) -d -m $(DIRMODE) \
+ $(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/Resources/English.lproj
+ $(INSTALL_DATA) $(RESSRCDIR)/Info.plist \
+ $(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/Resources/Info.plist
+ $(INSTALL_DATA) $(RESSRCDIR)/version.plist \
+ $(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/Resources/version.plist
+ $(INSTALL_DATA) $(RESSRCDIR)/English.lproj/InfoPlist.strings \
+ $(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/Resources/English.lproj/InfoPlist.strings
+ $(LN) -fsn $(VERSION) $(PYTHONFRAMEWORKDIR)/Versions/Current
+ $(LN) -fsn Versions/Current/$(PYTHONFRAMEWORK) $(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK)
+ $(LN) -fsn Versions/Current/Headers $(PYTHONFRAMEWORKDIR)/Headers
+ $(LN) -fsn Versions/Current/Resources $(PYTHONFRAMEWORKDIR)/Resources
+
+# This rule builds the Cygwin Python DLL and import library if configured
+# for a shared core library; otherwise, this rule is a noop.
+$(DLLLIBRARY) libpython$(VERSION).dll.a: $(LIBRARY_OBJS)
+ if test -n "$(DLLLIBRARY)"; then \
+ $(LDSHARED) -Wl,--out-implib=$@ -o $(DLLLIBRARY) $^ \
+ $(LIBS) $(MODLIBS) $(SYSLIBS); \
+ else true; \
+ fi
+
+
+oldsharedmods: $(SHAREDMODS)
+
+
+Makefile Modules/config.c: Makefile.pre \
+ $(srcdir)/Modules/config.c.in \
+ $(MAKESETUP) \
+ Modules/Setup.config \
+ Modules/Setup \
+ Modules/Setup.local
+ $(SHELL) $(MAKESETUP) -c $(srcdir)/Modules/config.c.in \
+ -s Modules \
+ Modules/Setup.config \
+ Modules/Setup.local \
+ Modules/Setup
+ @mv config.c Modules
+ @echo "The Makefile was updated, you may need to re-run make."
+
+
+Modules/Setup: $(srcdir)/Modules/Setup.dist
+ @if test -f Modules/Setup; then \
+ echo "-----------------------------------------------"; \
+ echo "Modules/Setup.dist is newer than Modules/Setup;"; \
+ echo "check to make sure you have all the updates you"; \
+ echo "need in your Modules/Setup file."; \
+ echo "Usually, copying Setup.dist to Setup will work."; \
+ echo "-----------------------------------------------"; \
+ fi
+
+############################################################################
+# Special rules for object files
+
+Modules/getbuildinfo.o: $(PARSER_OBJS) \
+ $(OBJECT_OBJS) \
+ $(PYTHON_OBJS) \
+ $(MODULE_OBJS) \
+ $(SIGNAL_OBJS) \
+ $(MODOBJS) \
+ $(srcdir)/Modules/getbuildinfo.c
+ $(CC) -c $(PY_CFLAGS) -DSVNVERSION=\"`LC_ALL=C $(SVNVERSION)`\" -o $@ $(srcdir)/Modules/getbuildinfo.c
+
+Modules/getpath.o: $(srcdir)/Modules/getpath.c Makefile
+ $(CC) -c $(PY_CFLAGS) -DPYTHONPATH='"$(PYTHONPATH)"' \
+ -DPREFIX='"$(prefix)"' \
+ -DEXEC_PREFIX='"$(exec_prefix)"' \
+ -DVERSION='"$(VERSION)"' \
+ -DVPATH='"$(VPATH)"' \
+ -o $@ $(srcdir)/Modules/getpath.c
+
+Modules/python.o: $(srcdir)/Modules/python.c
+ $(MAINCC) -c $(PY_CFLAGS) -o $@ $(srcdir)/Modules/python.c
+
+
+$(GRAMMAR_H) $(GRAMMAR_C): $(PGEN) $(GRAMMAR_INPUT)
+ -$(PGEN) $(GRAMMAR_INPUT) $(GRAMMAR_H) $(GRAMMAR_C)
+
+$(PGEN): $(PGENOBJS)
+ $(CC) $(OPT) $(LDFLAGS) $(PGENOBJS) $(LIBS) -o $(PGEN)
+
+Parser/grammar.o: $(srcdir)/Parser/grammar.c \
+ $(srcdir)/Include/token.h \
+ $(srcdir)/Include/grammar.h
+Parser/metagrammar.o: $(srcdir)/Parser/metagrammar.c
+
+Parser/tokenizer_pgen.o: $(srcdir)/Parser/tokenizer.c
+
+$(AST_H): $(AST_ASDL) $(ASDLGEN_FILES)
+ $(ASDLGEN) -h $(AST_H_DIR) $(AST_ASDL)
+
+$(AST_C): $(AST_ASDL) $(ASDLGEN_FILES)
+ $(ASDLGEN) -c $(AST_C_DIR) $(AST_ASDL)
+
+Python/compile.o Python/symtable.o: $(GRAMMAR_H) $(AST_H)
+
+Python/getplatform.o: $(srcdir)/Python/getplatform.c
+ $(CC) -c $(PY_CFLAGS) -DPLATFORM='"$(MACHDEP)"' -o $@ $(srcdir)/Python/getplatform.c
+
+Python/importdl.o: $(srcdir)/Python/importdl.c
+ $(CC) -c $(PY_CFLAGS) -I$(DLINCLDIR) -o $@ $(srcdir)/Python/importdl.c
+
+Objects/unicodectype.o: $(srcdir)/Objects/unicodectype.c \
+ $(srcdir)/Objects/unicodetype_db.h
+
+############################################################################
+# Header files
+
+PYTHON_HEADERS= \
+ Include/Python.h \
+ Include/Python-ast.h \
+ Include/asdl.h \
+ Include/abstract.h \
+ Include/boolobject.h \
+ Include/bufferobject.h \
+ Include/ceval.h \
+ Include/classobject.h \
+ Include/cobject.h \
+ Include/code.h \
+ Include/codecs.h \
+ Include/compile.h \
+ Include/complexobject.h \
+ Include/descrobject.h \
+ Include/dictobject.h \
+ Include/enumobject.h \
+ Include/genobject.h \
+ Include/fileobject.h \
+ Include/floatobject.h \
+ Include/funcobject.h \
+ Include/import.h \
+ Include/intobject.h \
+ Include/intrcheck.h \
+ Include/iterobject.h \
+ Include/listobject.h \
+ Include/longobject.h \
+ Include/methodobject.h \
+ Include/modsupport.h \
+ Include/moduleobject.h \
+ Include/object.h \
+ Include/objimpl.h \
+ Include/patchlevel.h \
+ Include/pyarena.h \
+ Include/pydebug.h \
+ Include/pyerrors.h \
+ Include/pyfpe.h \
+ Include/pymem.h \
+ Include/pyport.h \
+ Include/pystate.h \
+ Include/pythonrun.h \
+ Include/rangeobject.h \
+ Include/setobject.h \
+ Include/sliceobject.h \
+ Include/stringobject.h \
+ Include/structseq.h \
+ Include/structmember.h \
+ Include/symtable.h \
+ Include/sysmodule.h \
+ Include/traceback.h \
+ Include/tupleobject.h \
+ Include/unicodeobject.h \
+ Include/weakrefobject.h \
+ pyconfig.h
+
+$(LIBRARY_OBJS) $(MODOBJS) Modules/python.o: $(PYTHON_HEADERS)
+
+
+######################################################################
+
+# Test the interpreter (twice, once without .pyc files, once with)
+# In the past, we've had problems where bugs in the marshalling or
+# elsewhere caused bytecode read from .pyc files to behave differently
+# than bytecode generated directly from a .py source file. Sometimes
+# the bytecode read from a .pyc file had the bug, somtimes the directly
+# generated bytecode. This is sometimes a very shy bug needing a lot of
+# sample data.
+
+TESTOPTS= -l $(EXTRATESTOPTS)
+TESTPROG= $(srcdir)/Lib/test/regrtest.py
+TESTPYTHON= $(RUNSHARED) ./$(BUILDPYTHON) -E -tt
+test: all platform
+ -find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f
+ -$(TESTPYTHON) $(TESTPROG) $(TESTOPTS)
+ $(TESTPYTHON) $(TESTPROG) $(TESTOPTS)
+
+testall: all platform
+ -find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f
+ -$(TESTPYTHON) $(TESTPROG) $(TESTOPTS) -uall
+ $(TESTPYTHON) $(TESTPROG) $(TESTOPTS) -uall
+
+# Run the unitests for both architectures in a Universal build on OSX
+# Must be run on an Intel box.
+testuniversal: all platform
+ if [ `arch` != 'i386' ];then \
+ echo "This can only be used on OSX/i386" ;\
+ exit 1 ;\
+ fi
+ -find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f
+ -$(TESTPYTHON) $(TESTPROG) $(TESTOPTS) -uall
+ $(TESTPYTHON) $(TESTPROG) $(TESTOPTS) -uall
+ $(RUNSHARED) /usr/libexec/oah/translate ./$(BUILDPYTHON) -E -tt $(TESTPROG) $(TESTOPTS) -uall
+
+
+# Like testall, but with a single pass only
+buildbottest: all platform
+ $(TESTPYTHON) $(TESTPROG) $(TESTOPTS) -uall -rw
+
+QUICKTESTOPTS= $(TESTOPTS) -x test_thread test_signal test_strftime \
+ test_unicodedata test_re test_sre test_select test_poll \
+ test_linuxaudiodev test_struct test_sunaudiodev test_zlib
+quicktest: all platform
+ -find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f
+ -$(TESTPYTHON) $(TESTPROG) $(QUICKTESTOPTS)
+ $(TESTPYTHON) $(TESTPROG) $(QUICKTESTOPTS)
+
+MEMTESTOPTS= $(QUICKTESTOPTS) -x test_dl test___all__ test_fork1 \
+ test_longexp
+memtest: all platform
+ -rm -f $(srcdir)/Lib/test/*.py[co]
+ -$(TESTPYTHON) $(TESTPROG) $(MEMTESTOPTS)
+ $(TESTPYTHON) $(TESTPROG) $(MEMTESTOPTS)
+
+# Install everything
+install: @FRAMEWORKINSTALLFIRST@ altinstall bininstall maninstall @FRAMEWORKINSTALLLAST@
+
+# Install almost everything without disturbing previous versions
+altinstall: @FRAMEWORKALTINSTALLFIRST@ altbininstall libinstall inclinstall libainstall \
+ sharedinstall oldsharedinstall @FRAMEWORKALTINSTALLLAST@
+
+# Install shared libraries enabled by Setup
+DESTDIRS= $(exec_prefix) $(LIBDIR) $(BINLIBDEST) $(DESTSHARED)
+
+oldsharedinstall: $(DESTSHARED) $(SHAREDMODS)
+ @for i in X $(SHAREDMODS); do \
+ if test $$i != X; then \
+ echo $(INSTALL_SHARED) $$i $(DESTSHARED)/`basename $$i`; \
+ $(INSTALL_SHARED) $$i $(DESTDIR)$(DESTSHARED)/`basename $$i`; \
+ fi; \
+ done
+
+$(DESTSHARED):
+ @for i in $(DESTDIRS); \
+ do \
+ if test ! -d $(DESTDIR)$$i; then \
+ echo "Creating directory $$i"; \
+ $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$i; \
+ else true; \
+ fi; \
+ done
+
+
+# Install the interpreter (by creating a hard link to python$(VERSION))
+bininstall: altbininstall
+ -if test -f $(DESTDIR)$(BINDIR)/$(PYTHON) -o -h $(DESTDIR)$(BINDIR)/$(PYTHON); \
+ then rm -f $(DESTDIR)$(BINDIR)/$(PYTHON); \
+ else true; \
+ fi
+ (cd $(DESTDIR)$(BINDIR); $(LN) python$(VERSION)$(EXE) $(PYTHON))
+ (cd $(DESTDIR)$(BINDIR); $(LN) -sf python$(VERSION)-config python-config)
+
+# Install the interpreter with $(VERSION) affixed
+# This goes into $(exec_prefix)
+altbininstall: $(BUILDPYTHON)
+ @for i in $(BINDIR) $(LIBDIR); \
+ do \
+ if test ! -d $(DESTDIR)$$i; then \
+ echo "Creating directory $$i"; \
+ $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$i; \
+ else true; \
+ fi; \
+ done
+ $(INSTALL_PROGRAM) $(BUILDPYTHON) $(DESTDIR)$(BINDIR)/python$(VERSION)$(EXE)
+ if test -f libpython$(VERSION)$(SO); then \
+ if test "$(SO)" = .dll; then \
+ $(INSTALL_SHARED) libpython$(VERSION)$(SO) $(DESTDIR)$(BINDIR); \
+ else \
+ $(INSTALL_SHARED) libpython$(VERSION)$(SO) $(DESTDIR)$(LIBDIR)/$(INSTSONAME); \
+ if test libpython$(VERSION)$(SO) != $(INSTSONAME); then \
+ (cd $(DESTDIR)$(LIBDIR); $(LN) -sf $(INSTSONAME) libpython$(VERSION)$(SO)); \
+ fi \
+ fi; \
+ else true; \
+ fi
+
+# Install the manual page
+maninstall:
+ @for i in $(MANDIR) $(MANDIR)/man1; \
+ do \
+ if test ! -d $(DESTDIR)$$i; then \
+ echo "Creating directory $$i"; \
+ $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$i; \
+ else true; \
+ fi; \
+ done
+ $(INSTALL_DATA) $(srcdir)/Misc/python.man \
+ $(DESTDIR)$(MANDIR)/man1/python.1
+
+# Install the library
+PLATDIR= plat-$(MACHDEP)
+EXTRAPLATDIR= @EXTRAPLATDIR@
+EXTRAMACHDEPPATH=@EXTRAMACHDEPPATH@
+MACHDEPS= $(PLATDIR) $(EXTRAPLATDIR)
+XMLLIBSUBDIRS= xml xml/dom xml/etree xml/parsers xml/sax
+PLATMACDIRS= plat-mac plat-mac/Carbon plat-mac/lib-scriptpackages \
+ plat-mac/lib-scriptpackages/_builtinSuites \
+ plat-mac/lib-scriptpackages/CodeWarrior \
+ plat-mac/lib-scriptpackages/Explorer \
+ plat-mac/lib-scriptpackages/Finder \
+ plat-mac/lib-scriptpackages/Netscape \
+ plat-mac/lib-scriptpackages/StdSuites \
+ plat-mac/lib-scriptpackages/SystemEvents \
+ plat-mac/lib-scriptpackages/Terminal
+PLATMACPATH=:plat-mac:plat-mac/lib-scriptpackages
+LIBSUBDIRS= lib-tk site-packages test test/output test/data \
+ test/decimaltestdata \
+ encodings compiler hotshot \
+ email email/mime email/test email/test/data \
+ sqlite3 sqlite3/test \
+ logging bsddb bsddb/test csv wsgiref \
+ ctypes ctypes/test ctypes/macholib idlelib idlelib/Icons \
+ distutils distutils/command distutils/tests $(XMLLIBSUBDIRS) \
+ setuptools setuptools/command setuptools/tests setuptools.egg-info \
+ curses $(MACHDEPS)
+libinstall: $(BUILDPYTHON) $(srcdir)/Lib/$(PLATDIR)
+ @for i in $(SCRIPTDIR) $(LIBDEST); \
+ do \
+ if test ! -d $(DESTDIR)$$i; then \
+ echo "Creating directory $$i"; \
+ $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$i; \
+ else true; \
+ fi; \
+ done
+ @for d in $(LIBSUBDIRS); \
+ do \
+ a=$(srcdir)/Lib/$$d; \
+ if test ! -d $$a; then continue; else true; fi; \
+ b=$(LIBDEST)/$$d; \
+ if test ! -d $(DESTDIR)$$b; then \
+ echo "Creating directory $$b"; \
+ $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$b; \
+ else true; \
+ fi; \
+ done
+ @for i in $(srcdir)/Lib/*.py $(srcdir)/Lib/*.doc $(srcdir)/Lib/*.egg-info ; \
+ do \
+ if test -x $$i; then \
+ $(INSTALL_SCRIPT) $$i $(DESTDIR)$(LIBDEST); \
+ echo $(INSTALL_SCRIPT) $$i $(LIBDEST); \
+ else \
+ $(INSTALL_DATA) $$i $(DESTDIR)$(LIBDEST); \
+ echo $(INSTALL_DATA) $$i $(LIBDEST); \
+ fi; \
+ done
+ @for d in $(LIBSUBDIRS); \
+ do \
+ a=$(srcdir)/Lib/$$d; \
+ if test ! -d $$a; then continue; else true; fi; \
+ if test `ls $$a | wc -l` -lt 1; then continue; fi; \
+ b=$(LIBDEST)/$$d; \
+ for i in $$a/*; \
+ do \
+ case $$i in \
+ *CVS) ;; \
+ *.py[co]) ;; \
+ *.orig) ;; \
+ *~) ;; \
+ *) \
+ if test -d $$i; then continue; fi; \
+ if test -x $$i; then \
+ echo $(INSTALL_SCRIPT) $$i $$b; \
+ $(INSTALL_SCRIPT) $$i $(DESTDIR)$$b; \
+ else \
+ echo $(INSTALL_DATA) $$i $$b; \
+ $(INSTALL_DATA) $$i $(DESTDIR)$$b; \
+ fi;; \
+ esac; \
+ done; \
+ done
+ $(INSTALL_DATA) $(srcdir)/LICENSE $(DESTDIR)$(LIBDEST)/LICENSE.txt
+ PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \
+ ./$(BUILDPYTHON) -Wi -tt $(DESTDIR)$(LIBDEST)/compileall.py \
+ -d $(LIBDEST) -f \
+ -x 'bad_coding|badsyntax|site-packages' $(DESTDIR)$(LIBDEST)
+ PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \
+ ./$(BUILDPYTHON) -Wi -tt -O $(DESTDIR)$(LIBDEST)/compileall.py \
+ -d $(LIBDEST) -f \
+ -x 'bad_coding|badsyntax|site-packages' $(DESTDIR)$(LIBDEST)
+ -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \
+ ./$(BUILDPYTHON) -Wi -t $(DESTDIR)$(LIBDEST)/compileall.py \
+ -d $(LIBDEST)/site-packages -f \
+ -x badsyntax $(DESTDIR)$(LIBDEST)/site-packages
+ -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \
+ ./$(BUILDPYTHON) -Wi -t -O $(DESTDIR)$(LIBDEST)/compileall.py \
+ -d $(LIBDEST)/site-packages -f \
+ -x badsyntax $(DESTDIR)$(LIBDEST)/site-packages
+
+# Create the PLATDIR source directory, if one wasn't distributed..
+$(srcdir)/Lib/$(PLATDIR):
+ mkdir $(srcdir)/Lib/$(PLATDIR)
+ cp $(srcdir)/Lib/plat-generic/regen $(srcdir)/Lib/$(PLATDIR)/regen
+ export PATH; PATH="`pwd`:$$PATH"; \
+ export PYTHONPATH; PYTHONPATH="`pwd`/Lib"; \
+ export DYLD_FRAMEWORK_PATH; DYLD_FRAMEWORK_PATH="`pwd`"; \
+ export EXE; EXE="$(BUILDEXE)"; \
+ cd $(srcdir)/Lib/$(PLATDIR); ./regen
+
+# Install the include files
+INCLDIRSTOMAKE=$(INCLUDEDIR) $(CONFINCLUDEDIR) $(INCLUDEPY) $(CONFINCLUDEPY)
+inclinstall:
+ @for i in $(INCLDIRSTOMAKE); \
+ do \
+ if test ! -d $(DESTDIR)$$i; then \
+ echo "Creating directory $$i"; \
+ $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$i; \
+ else true; \
+ fi; \
+ done
+ @for i in $(srcdir)/Include/*.h; \
+ do \
+ echo $(INSTALL_DATA) $$i $(INCLUDEPY); \
+ $(INSTALL_DATA) $$i $(DESTDIR)$(INCLUDEPY); \
+ done
+ $(INSTALL_DATA) pyconfig.h $(DESTDIR)$(CONFINCLUDEPY)/pyconfig.h
+
+# Install the library and miscellaneous stuff needed for extending/embedding
+# This goes into $(exec_prefix)
+LIBPL= $(LIBP)/config
+libainstall: all
+ @for i in $(LIBDIR) $(LIBP) $(LIBPL); \
+ do \
+ if test ! -d $(DESTDIR)$$i; then \
+ echo "Creating directory $$i"; \
+ $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$i; \
+ else true; \
+ fi; \
+ done
+ @if test -d $(LIBRARY); then :; else \
+ if test "$(PYTHONFRAMEWORKDIR)" = no-framework; then \
+ if test "$(SO)" = .dll; then \
+ $(INSTALL_DATA) $(LDLIBRARY) $(DESTDIR)$(LIBPL) ; \
+ else \
+ $(INSTALL_DATA) $(LIBRARY) $(DESTDIR)$(LIBPL)/$(LIBRARY) ; \
+ $(RANLIB) $(DESTDIR)$(LIBPL)/$(LIBRARY) ; \
+ fi; \
+ else \
+ echo Skip install of $(LIBRARY) - use make frameworkinstall; \
+ fi; \
+ fi
+ $(INSTALL_DATA) Modules/config.c $(DESTDIR)$(LIBPL)/config.c
+ $(INSTALL_DATA) Modules/python.o $(DESTDIR)$(LIBPL)/python.o
+ $(INSTALL_DATA) $(srcdir)/Modules/config.c.in $(DESTDIR)$(LIBPL)/config.c.in
+ $(INSTALL_DATA) Makefile $(DESTDIR)$(LIBPL)/Makefile
+ $(INSTALL_DATA) Modules/Setup $(DESTDIR)$(LIBPL)/Setup
+ $(INSTALL_DATA) Modules/Setup.local $(DESTDIR)$(LIBPL)/Setup.local
+ $(INSTALL_DATA) Modules/Setup.config $(DESTDIR)$(LIBPL)/Setup.config
+ $(INSTALL_SCRIPT) $(srcdir)/Modules/makesetup $(DESTDIR)$(LIBPL)/makesetup
+ $(INSTALL_SCRIPT) $(srcdir)/install-sh $(DESTDIR)$(LIBPL)/install-sh
+ # Substitution happens here, as the completely-expanded BINDIR
+ # is not available in configure
+ sed -e "s,@EXENAME@,$(BINDIR)/python$(VERSION)$(EXE)," < $(srcdir)/Misc/python-config.in >python-config
+ $(INSTALL_SCRIPT) python-config $(DESTDIR)$(BINDIR)/python$(VERSION)-config
+ rm python-config
+ @if [ -s Modules/python.exp -a \
+ "`echo $(MACHDEP) | sed 's/^\(...\).*/\1/'`" = "aix" ]; then \
+ echo; echo "Installing support files for building shared extension modules on AIX:"; \
+ $(INSTALL_DATA) Modules/python.exp \
+ $(DESTDIR)$(LIBPL)/python.exp; \
+ echo; echo "$(LIBPL)/python.exp"; \
+ $(INSTALL_SCRIPT) $(srcdir)/Modules/makexp_aix \
+ $(DESTDIR)$(LIBPL)/makexp_aix; \
+ echo "$(LIBPL)/makexp_aix"; \
+ $(INSTALL_SCRIPT) $(srcdir)/Modules/ld_so_aix \
+ $(DESTDIR)$(LIBPL)/ld_so_aix; \
+ echo "$(LIBPL)/ld_so_aix"; \
+ echo; echo "See Misc/AIX-NOTES for details."; \
+ else true; \
+ fi
+ @case "$(MACHDEP)" in beos*) \
+ echo; echo "Installing support files for building shared extension modules on BeOS:"; \
+ $(INSTALL_DATA) Misc/BeOS-NOTES $(DESTDIR)$(LIBPL)/README; \
+ echo; echo "$(LIBPL)/README"; \
+ $(INSTALL_SCRIPT) Modules/ar_beos $(DESTDIR)$(LIBPL)/ar_beos; \
+ echo "$(LIBPL)/ar_beos"; \
+ $(INSTALL_SCRIPT) Modules/ld_so_beos $(DESTDIR)$(LIBPL)/ld_so_beos; \
+ echo "$(LIBPL)/ld_so_beos"; \
+ echo; echo "See Misc/BeOS-NOTES for details."; \
+ ;; \
+ esac
+
+# Install the dynamically loadable modules
+# This goes into $(exec_prefix)
+sharedinstall:
+ $(RUNSHARED) ./$(BUILDPYTHON) -E $(srcdir)/setup.py install \
+ --prefix=$(prefix) \
+ --install-scripts=$(BINDIR) \
+ --install-platlib=$(DESTSHARED) \
+ --root=/$(DESTDIR)
+
+# Here are a couple of targets for MacOSX again, to install a full
+# framework-based Python. frameworkinstall installs everything, the
+# subtargets install specific parts. Much of the actual work is offloaded to
+# the Makefile in Mac
+#
+#
+# This target is here for backward compatiblity, previous versions of Python
+# hadn't integrated framework installation in the normal install process.
+frameworkinstall: install
+
+# On install, we re-make the framework
+# structure in the install location, /Library/Frameworks/ or the argument to
+# --enable-framework. If --enable-framework has been specified then we have
+# automatically set prefix to the location deep down in the framework, so we
+# only have to cater for the structural bits of the framework.
+
+frameworkinstallframework: frameworkinstallstructure install frameworkinstallmaclib
+
+frameworkinstallstructure: $(LDLIBRARY)
+ @if test "$(PYTHONFRAMEWORKDIR)" = no-framework; then \
+ echo Not configured with --enable-framework; \
+ exit 1; \
+ else true; \
+ fi
+ @for i in $(prefix)/Resources/English.lproj $(prefix)/lib; do\
+ if test ! -d $(DESTDIR)$$i; then \
+ echo "Creating directory $(DESTDIR)$$i"; \
+ $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$i; \
+ else true; \
+ fi; \
+ done
+ $(LN) -fsn include/python$(VERSION) $(DESTDIR)$(prefix)/Headers
+ $(INSTALL_DATA) $(RESSRCDIR)/Info.plist $(DESTDIR)$(prefix)/Resources/Info.plist
+ $(INSTALL_DATA) $(RESSRCDIR)/version.plist $(DESTDIR)$(prefix)/Resources/version.plist
+ $(INSTALL_DATA) $(RESSRCDIR)/English.lproj/InfoPlist.strings \
+ $(DESTDIR)$(prefix)/Resources/English.lproj/InfoPlist.strings
+ $(LN) -fsn $(VERSION) $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Versions/Current
+ $(LN) -fsn Versions/Current/Python $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Python
+ $(LN) -fsn Versions/Current/Headers $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Headers
+ $(LN) -fsn Versions/Current/Resources $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Resources
+ $(INSTALL_SHARED) $(LDLIBRARY) $(DESTDIR)$(PYTHONFRAMEWORKPREFIX)/$(LDLIBRARY)
+
+# This installs Mac/Lib into the framework
+# Install a number of symlinks to keep software that expects a normal unix
+# install (which includes python-config) happy.
+frameworkinstallmaclib:
+ ln -fs "../../../Python" "$(DESTDIR)$(prefix)/lib/python$(VERSION)/config/libpython$(VERSION).a"
+ cd Mac && $(MAKE) installmacsubtree DESTDIR="$(DESTDIR)"
+
+# This installs the IDE, the Launcher and other apps into /Applications
+frameworkinstallapps:
+ cd Mac && $(MAKE) installapps DESTDIR="$(DESTDIR)"
+
+# This install the unix python and pythonw tools in /usr/local/bin
+frameworkinstallunixtools:
+ cd Mac && $(MAKE) installunixtools DESTDIR="$(DESTDIR)"
+
+frameworkaltinstallunixtools:
+ cd Mac && $(MAKE) altinstallunixtools DESTDIR="$(DESTDIR)"
+
+# This installs the Demos and Tools into the applications directory.
+# It is not part of a normal frameworkinstall
+frameworkinstallextras:
+ cd Mac && Make installextras DESTDIR="$(DESTDIR)"
+
+# This installs a few of the useful scripts in Tools/scripts
+scriptsinstall:
+ SRCDIR=$(srcdir) $(RUNSHARED) \
+ ./$(BUILDPYTHON) $(srcdir)/Tools/scripts/setup.py install \
+ --prefix=$(prefix) \
+ --install-scripts=$(BINDIR) \
+ --root=/$(DESTDIR)
+
+# Build the toplevel Makefile
+Makefile.pre: Makefile.pre.in config.status
+ CONFIG_FILES=Makefile.pre CONFIG_HEADERS= $(SHELL) config.status
+ $(MAKE) -f Makefile.pre Makefile
+
+# Run the configure script.
+config.status: $(srcdir)/configure
+ $(SHELL) $(srcdir)/configure $(CONFIG_ARGS)
+
+.PRECIOUS: config.status $(BUILDPYTHON) Makefile Makefile.pre
+
+# Some make's put the object file in the current directory
+.c.o:
+ $(CC) -c $(PY_CFLAGS) -o $@ $<
+
+# Run reindent on the library
+reindent:
+ ./python$(EXEEXT) $(srcdir)/Tools/scripts/reindent.py -r $(srcdir)/Lib
+
+# Rerun configure with the same options as it was run last time,
+# provided the config.status script exists
+recheck:
+ $(SHELL) config.status --recheck
+ $(SHELL) config.status
+
+# Rebuild the configure script from configure.in; also rebuild pyconfig.h.in
+autoconf:
+ (cd $(srcdir); autoconf)
+ (cd $(srcdir); autoheader)
+
+# Create a tags file for vi
+tags::
+ cd $(srcdir); \
+ ctags -w -t Include/*.h; \
+ for i in $(SRCDIRS); do ctags -w -t -a $$i/*.[ch]; \
+ done; \
+ sort -o tags tags
+
+# Create a tags file for GNU Emacs
+TAGS::
+ cd $(srcdir); \
+ etags Include/*.h; \
+ for i in $(SRCDIRS); do etags -a $$i/*.[ch]; done
+
+# Sanitation targets -- clean leaves libraries, executables and tags
+# files, which clobber removes those as well
+pycremoval:
+ find $(srcdir) -name '*.py[co]' -exec rm -f {} ';'
+
+clean: pycremoval
+ find . -name '*.o' -exec rm -f {} ';'
+ find . -name '*.s[ol]' -exec rm -f {} ';'
+ find $(srcdir)/build -name 'fficonfig.h' -exec rm -f {} ';' || true
+ find $(srcdir)/build -name 'fficonfig.py' -exec rm -f {} ';' || true
+
+clobber: clean
+ -rm -f $(BUILDPYTHON) $(PGEN) $(LIBRARY) $(LDLIBRARY) $(DLLLIBRARY) \
+ tags TAGS \
+ config.cache config.log pyconfig.h Modules/config.c
+ -rm -rf build platform
+ -rm -rf $(PYTHONFRAMEWORKDIR)
+
+# Make things extra clean, before making a distribution:
+# remove all generated files, even Makefile[.pre]
+# Keep configure and Python-ast.[ch], it's possible they can't be generated
+distclean: clobber
+ -rm -f core Makefile Makefile.pre config.status \
+ Modules/Setup Modules/Setup.local Modules/Setup.config
+ find $(srcdir) '(' -name '*.fdc' -o -name '*~' \
+ -o -name '[@,#]*' -o -name '*.old' \
+ -o -name '*.orig' -o -name '*.rej' \
+ -o -name '*.bak' ')' \
+ -exec rm -f {} ';'
+
+# Check for smelly exported symbols (not starting with Py/_Py)
+smelly: all
+ nm -p $(LIBRARY) | \
+ sed -n "/ [TDB] /s/.* //p" | grep -v "^_*Py" | sort -u; \
+
+# Find files with funny names
+funny:
+ find $(DISTDIRS) -type d \
+ -o -name '*.[chs]' \
+ -o -name '*.py' \
+ -o -name '*.doc' \
+ -o -name '*.sty' \
+ -o -name '*.bib' \
+ -o -name '*.dat' \
+ -o -name '*.el' \
+ -o -name '*.fd' \
+ -o -name '*.in' \
+ -o -name '*.tex' \
+ -o -name '*,[vpt]' \
+ -o -name 'Setup' \
+ -o -name 'Setup.*' \
+ -o -name README \
+ -o -name Makefile \
+ -o -name ChangeLog \
+ -o -name Repository \
+ -o -name Root \
+ -o -name Entries \
+ -o -name Tag \
+ -o -name tags \
+ -o -name TAGS \
+ -o -name .cvsignore \
+ -o -name MANIFEST \
+ -o -print
+
+# Dependencies
+
+Python/thread.o: @THREADHEADERS@
+
+# Declare targets that aren't real files
+.PHONY: all sharedmods oldsharedmods test quicktest memtest
+.PHONY: install altinstall oldsharedinstall bininstall altbininstall
+.PHONY: maninstall libinstall inclinstall libainstall sharedinstall
+.PHONY: frameworkinstall frameworkinstallframework frameworkinstallstructure
+.PHONY: frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools
+.PHONY: frameworkaltinstallunixtools recheck autoconf clean clobber distclean
+.PHONY: smelly funny
+
+# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
--- /dev/null
+++ b/sys/lib/python/contextlib.py
@@ -1,0 +1,154 @@
+"""Utilities for with-statement contexts. See PEP 343."""
+
+import sys
+
+__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:
+ 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>
+
+ """
+ def helper(*args, **kwds):
+ return GeneratorContextManager(func(*args, **kwds))
+ try:
+ helper.__name__ = func.__name__
+ helper.__doc__ = func.__doc__
+ helper.__dict__ = func.__dict__
+ except:
+ pass
+ return helper
+
+
+@contextmanager
+def nested(*managers):
+ """Support multiple context managers in a single with-statement.
+
+ Code like this:
+
+ with nested(A, B, C) as (X, Y, Z):
+ <body>
+
+ is equivalent to this:
+
+ with A as X:
+ with B as Y:
+ with C as Z:
+ <body>
+
+ """
+ exits = []
+ vars = []
+ exc = (None, None, None)
+ try:
+ 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()
--- /dev/null
+++ b/sys/lib/python/cookielib.py
@@ -1,0 +1,1776 @@
+"""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', '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 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)
+ "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.
+ version_set = True
+ if k == "expires":
+ # convert expires date to seconds since epoch
+ if v.startswith('"'): v = v[1:]
+ if v.endswith('"'): v = v[:-1]
+ v = http2time(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):
+ """request-URI, as defined by RFC 2965."""
+ url = request.get_full_url()
+ #scheme, netloc, path, parameters, query, frag = urlparse.urlparse(url)
+ #req_path = escape_path("".join(urlparse.urlparse(url)[2:]))
+ path, parameters, query, frag = urlparse.urlparse(url)[2:]
+ if parameters:
+ path = "%s;%s" % (path, parameters)
+ path = escape_path(path)
+ req_path = urlparse.urlunparse(("", "", path, "", query, frag))
+ if not req_path.startswith("/"):
+ # fix bad RFC 2396 absoluteURI
+ req_path = "/"+req_path
+ return req_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 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
+ def decreasing_size(a, b): return cmp(len(b.path), len(a.path))
+ cookies.sort(decreasing_size)
+
+ 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()
+
+ 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
+
+ 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: version = int(version)
+ 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()
+ self._policy._now = self._now = int(time.time())
+
+ if self._policy.set_ok(cookie, request):
+ self.set_cookie(cookie)
+
+ 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()
+ 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)
+ 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()
+ for cookie in self:
+ if cookie.discard:
+ self.clear(cookie.domain, cookie.path, cookie.name)
+ 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()
+ now = time.time()
+ for cookie in self:
+ if cookie.is_expired(now):
+ self.clear(cookie.domain, cookie.path, cookie.name)
+ 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()
+
+ old_state = copy.deepcopy(self._cookies)
+ self._cookies = {}
+ try:
+ self.load(filename, ignore_discard, ignore_expires)
+ except (LoadError, IOError):
+ self._cookies = old_state
+ raise
+
+ self._cookies_lock.release()
+
+from _LWPCookieJar import LWPCookieJar, lwp_cookie_str
+from _MozillaCookieJar import MozillaCookieJar
--- /dev/null
+++ b/sys/lib/python/copy.py
@@ -1,0 +1,414 @@
+"""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
+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,
+ types.FunctionType):
+ 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[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
+
+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 _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 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
+ 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)
+ 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)
+
+if __name__ == '__main__':
+ _test()
--- /dev/null
+++ b/sys/lib/python/copy_reg.py
@@ -1,0 +1,200 @@
+"""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 callable(pickle_function):
+ 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 callable(object):
+ 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)
+ 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.
--- /dev/null
+++ b/sys/lib/python/csv.py
@@ -1,0 +1,415 @@
+
+"""
+csv.py - read/write/investigate CSV files
+"""
+
+import re
+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", "excel", "excel_tab", "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)
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ row = self.reader.next()
+ if self.fieldnames is None:
+ self.fieldnames = row
+ row = self.reader.next()
+
+ # 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 _dict_to_list(self, rowdict):
+ if self.extrasaction == "raise":
+ for k in rowdict.keys():
+ if k not in self.fieldnames:
+ raise ValueError, "dict contains fields not in fieldnames"
+ 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, 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 = ''
+ doublequote = False
+
+ 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:
+ return ('', None, 0) # (quotechar, delimiter, skipinitialspace)
+
+ 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
+
+ return (quotechar, 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 freqencies 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
--- /dev/null
+++ b/sys/lib/python/ctypes/__init__.py
@@ -1,0 +1,529 @@
+######################################################################
+# This file should be kept compatible with Python 2.3, see PEP 291. #
+######################################################################
+"""create and manipulate C data types in Python"""
+
+import os as _os, sys as _sys
+
+__version__ = "1.0.2"
+
+from _ctypes import Union, Structure, Array
+from _ctypes import _Pointer
+from _ctypes import CFuncPtr as _CFuncPtr
+from _ctypes import __version__ as _ctypes_version
+from _ctypes import RTLD_LOCAL, RTLD_GLOBAL
+from _ctypes import ArgumentError
+
+from struct import calcsize as _calcsize
+
+if __version__ != _ctypes_version:
+ raise Exception, ("Version number mismatch", __version__, _ctypes_version)
+
+if _os.name in ("nt", "ce"):
+ from _ctypes import FormatError
+
+DEFAULT_MODE = RTLD_LOCAL
+if _os.name == "posix" and _sys.platform == "darwin":
+ import gestalt
+
+ # gestalt.gestalt("sysv") returns the version number of the
+ # currently active system file as BCD.
+ # On OS X 10.4.6 -> 0x1046
+ # On OS X 10.2.8 -> 0x1028
+ # See also http://www.rgaros.nl/gestalt/
+ #
+ # On OS X 10.3, we use RTLD_GLOBAL as default mode
+ # because RTLD_LOCAL does not work at least on some
+ # libraries.
+
+ if gestalt.gestalt("sysv") < 0x1040:
+ DEFAULT_MODE = RTLD_GLOBAL
+
+from _ctypes import FUNCFLAG_CDECL as _FUNCFLAG_CDECL, \
+ FUNCFLAG_PYTHONAPI as _FUNCFLAG_PYTHONAPI
+
+"""
+WINOLEAPI -> HRESULT
+WINOLEAPI_(type)
+
+STDMETHODCALLTYPE
+
+STDMETHOD(name)
+STDMETHOD_(type, name)
+
+STDAPICALLTYPE
+"""
+
+def create_string_buffer(init, size=None):
+ """create_string_buffer(aString) -> character array
+ create_string_buffer(anInteger) -> character array
+ create_string_buffer(aString, anInteger) -> character array
+ """
+ if isinstance(init, (str, unicode)):
+ if size is None:
+ size = len(init)+1
+ buftype = c_char * size
+ buf = buftype()
+ buf.value = init
+ return buf
+ elif isinstance(init, (int, long)):
+ buftype = c_char * init
+ buf = buftype()
+ return buf
+ raise TypeError, init
+
+def c_buffer(init, size=None):
+## "deprecated, use create_string_buffer instead"
+## import warnings
+## warnings.warn("c_buffer is deprecated, use create_string_buffer instead",
+## DeprecationWarning, stacklevel=2)
+ return create_string_buffer(init, size)
+
+_c_functype_cache = {}
+def CFUNCTYPE(restype, *argtypes):
+ """CFUNCTYPE(restype, *argtypes) -> function prototype.
+
+ restype: the result type
+ argtypes: a sequence specifying the argument types
+
+ The function prototype can be called in different ways to create a
+ callable object:
+
+ prototype(integer address) -> foreign function
+ prototype(callable) -> create and return a C callable function from callable
+ prototype(integer index, method name[, paramflags]) -> foreign function calling a COM method
+ prototype((ordinal number, dll object)[, paramflags]) -> foreign function exported by ordinal
+ prototype((function name, dll object)[, paramflags]) -> foreign function exported by name
+ """
+ try:
+ return _c_functype_cache[(restype, argtypes)]
+ except KeyError:
+ class CFunctionType(_CFuncPtr):
+ _argtypes_ = argtypes
+ _restype_ = restype
+ _flags_ = _FUNCFLAG_CDECL
+ _c_functype_cache[(restype, argtypes)] = CFunctionType
+ return CFunctionType
+
+if _os.name in ("nt", "ce"):
+ from _ctypes import LoadLibrary as _dlopen
+ from _ctypes import FUNCFLAG_STDCALL as _FUNCFLAG_STDCALL
+ if _os.name == "ce":
+ # 'ce' doesn't have the stdcall calling convention
+ _FUNCFLAG_STDCALL = _FUNCFLAG_CDECL
+
+ _win_functype_cache = {}
+ def WINFUNCTYPE(restype, *argtypes):
+ # docstring set later (very similar to CFUNCTYPE.__doc__)
+ try:
+ return _win_functype_cache[(restype, argtypes)]
+ except KeyError:
+ class WinFunctionType(_CFuncPtr):
+ _argtypes_ = argtypes
+ _restype_ = restype
+ _flags_ = _FUNCFLAG_STDCALL
+ _win_functype_cache[(restype, argtypes)] = WinFunctionType
+ return WinFunctionType
+ if WINFUNCTYPE.__doc__:
+ WINFUNCTYPE.__doc__ = CFUNCTYPE.__doc__.replace("CFUNCTYPE", "WINFUNCTYPE")
+
+elif _os.name == "posix":
+ from _ctypes import dlopen as _dlopen
+
+from _ctypes import sizeof, byref, addressof, alignment, resize
+from _ctypes import _SimpleCData
+
+def _check_size(typ, typecode=None):
+ # Check if sizeof(ctypes_type) against struct.calcsize. This
+ # should protect somewhat against a misconfigured libffi.
+ from struct import calcsize
+ if typecode is None:
+ # Most _type_ codes are the same as used in struct
+ typecode = typ._type_
+ actual, required = sizeof(typ), calcsize(typecode)
+ if actual != required:
+ raise SystemError("sizeof(%s) wrong: %d instead of %d" % \
+ (typ, actual, required))
+
+class py_object(_SimpleCData):
+ _type_ = "O"
+ def __repr__(self):
+ try:
+ return super(py_object, self).__repr__()
+ except ValueError:
+ return "%s(<NULL>)" % type(self).__name__
+_check_size(py_object, "P")
+
+class c_short(_SimpleCData):
+ _type_ = "h"
+_check_size(c_short)
+
+class c_ushort(_SimpleCData):
+ _type_ = "H"
+_check_size(c_ushort)
+
+class c_long(_SimpleCData):
+ _type_ = "l"
+_check_size(c_long)
+
+class c_ulong(_SimpleCData):
+ _type_ = "L"
+_check_size(c_ulong)
+
+if _calcsize("i") == _calcsize("l"):
+ # if int and long have the same size, make c_int an alias for c_long
+ c_int = c_long
+ c_uint = c_ulong
+else:
+ class c_int(_SimpleCData):
+ _type_ = "i"
+ _check_size(c_int)
+
+ class c_uint(_SimpleCData):
+ _type_ = "I"
+ _check_size(c_uint)
+
+class c_float(_SimpleCData):
+ _type_ = "f"
+_check_size(c_float)
+
+class c_double(_SimpleCData):
+ _type_ = "d"
+_check_size(c_double)
+
+if _calcsize("l") == _calcsize("q"):
+ # if long and long long have the same size, make c_longlong an alias for c_long
+ c_longlong = c_long
+ c_ulonglong = c_ulong
+else:
+ class c_longlong(_SimpleCData):
+ _type_ = "q"
+ _check_size(c_longlong)
+
+ class c_ulonglong(_SimpleCData):
+ _type_ = "Q"
+ ## def from_param(cls, val):
+ ## return ('d', float(val), val)
+ ## from_param = classmethod(from_param)
+ _check_size(c_ulonglong)
+
+class c_ubyte(_SimpleCData):
+ _type_ = "B"
+c_ubyte.__ctype_le__ = c_ubyte.__ctype_be__ = c_ubyte
+# backward compatibility:
+##c_uchar = c_ubyte
+_check_size(c_ubyte)
+
+class c_byte(_SimpleCData):
+ _type_ = "b"
+c_byte.__ctype_le__ = c_byte.__ctype_be__ = c_byte
+_check_size(c_byte)
+
+class c_char(_SimpleCData):
+ _type_ = "c"
+c_char.__ctype_le__ = c_char.__ctype_be__ = c_char
+_check_size(c_char)
+
+class c_char_p(_SimpleCData):
+ _type_ = "z"
+_check_size(c_char_p, "P")
+
+class c_void_p(_SimpleCData):
+ _type_ = "P"
+c_voidp = c_void_p # backwards compatibility (to a bug)
+_check_size(c_void_p)
+
+# This cache maps types to pointers to them.
+_pointer_type_cache = {}
+
+def POINTER(cls):
+ try:
+ return _pointer_type_cache[cls]
+ except KeyError:
+ pass
+ if type(cls) is str:
+ klass = type(_Pointer)("LP_%s" % cls,
+ (_Pointer,),
+ {})
+ _pointer_type_cache[id(klass)] = klass
+ return klass
+ else:
+ name = "LP_%s" % cls.__name__
+ klass = type(_Pointer)(name,
+ (_Pointer,),
+ {'_type_': cls})
+ _pointer_type_cache[cls] = klass
+ return klass
+
+try:
+ from _ctypes import set_conversion_mode
+except ImportError:
+ pass
+else:
+ if _os.name in ("nt", "ce"):
+ set_conversion_mode("mbcs", "ignore")
+ else:
+ set_conversion_mode("ascii", "strict")
+
+ class c_wchar_p(_SimpleCData):
+ _type_ = "Z"
+
+ class c_wchar(_SimpleCData):
+ _type_ = "u"
+
+ POINTER(c_wchar).from_param = c_wchar_p.from_param #_SimpleCData.c_wchar_p_from_param
+
+ def create_unicode_buffer(init, size=None):
+ """create_unicode_buffer(aString) -> character array
+ create_unicode_buffer(anInteger) -> character array
+ create_unicode_buffer(aString, anInteger) -> character array
+ """
+ if isinstance(init, (str, unicode)):
+ if size is None:
+ size = len(init)+1
+ buftype = c_wchar * size
+ buf = buftype()
+ buf.value = init
+ return buf
+ elif isinstance(init, (int, long)):
+ buftype = c_wchar * init
+ buf = buftype()
+ return buf
+ raise TypeError, init
+
+POINTER(c_char).from_param = c_char_p.from_param #_SimpleCData.c_char_p_from_param
+
+# XXX Deprecated
+def SetPointerType(pointer, cls):
+ if _pointer_type_cache.get(cls, None) is not None:
+ raise RuntimeError, \
+ "This type already exists in the cache"
+ if not _pointer_type_cache.has_key(id(pointer)):
+ raise RuntimeError, \
+ "What's this???"
+ pointer.set_type(cls)
+ _pointer_type_cache[cls] = pointer
+ del _pointer_type_cache[id(pointer)]
+
+
+def pointer(inst):
+ return POINTER(type(inst))(inst)
+
+# XXX Deprecated
+def ARRAY(typ, len):
+ return typ * len
+
+################################################################
+
+
+class CDLL(object):
+ """An instance of this class represents a loaded dll/shared
+ library, exporting functions using the standard C calling
+ convention (named 'cdecl' on Windows).
+
+ The exported functions can be accessed as attributes, or by
+ indexing with the function name. Examples:
+
+ <obj>.qsort -> callable object
+ <obj>['qsort'] -> callable object
+
+ Calling the functions releases the Python GIL during the call and
+ reaquires it afterwards.
+ """
+ class _FuncPtr(_CFuncPtr):
+ _flags_ = _FUNCFLAG_CDECL
+ _restype_ = c_int # default, can be overridden in instances
+
+ def __init__(self, name, mode=DEFAULT_MODE, handle=None):
+ self._name = name
+ if handle is None:
+ self._handle = _dlopen(self._name, mode)
+ else:
+ self._handle = handle
+
+ def __repr__(self):
+ return "<%s '%s', handle %x at %x>" % \
+ (self.__class__.__name__, self._name,
+ (self._handle & (_sys.maxint*2 + 1)),
+ id(self) & (_sys.maxint*2 + 1))
+
+ 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_or_ordinal):
+ func = self._FuncPtr((name_or_ordinal, self))
+ if not isinstance(name_or_ordinal, (int, long)):
+ func.__name__ = name_or_ordinal
+ return func
+
+class PyDLL(CDLL):
+ """This class represents the Python library itself. It allows to
+ access Python API functions. The GIL is not released, and
+ Python exceptions are handled correctly.
+ """
+ class _FuncPtr(_CFuncPtr):
+ _flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI
+ _restype_ = c_int # default, can be overridden in instances
+
+if _os.name in ("nt", "ce"):
+
+ class WinDLL(CDLL):
+ """This class represents a dll exporting functions using the
+ Windows stdcall calling convention.
+ """
+ class _FuncPtr(_CFuncPtr):
+ _flags_ = _FUNCFLAG_STDCALL
+ _restype_ = c_int # default, can be overridden in instances
+
+ # XXX Hm, what about HRESULT as normal parameter?
+ # Mustn't it derive from c_long then?
+ from _ctypes import _check_HRESULT, _SimpleCData
+ class HRESULT(_SimpleCData):
+ _type_ = "l"
+ # _check_retval_ is called with the function's result when it
+ # is used as restype. It checks for the FAILED bit, and
+ # raises a WindowsError if it is set.
+ #
+ # The _check_retval_ method is implemented in C, so that the
+ # method definition itself is not included in the traceback
+ # when it raises an error - that is what we want (and Python
+ # doesn't have a way to raise an exception in the caller's
+ # frame).
+ _check_retval_ = _check_HRESULT
+
+ class OleDLL(CDLL):
+ """This class represents a dll exporting functions using the
+ Windows stdcall calling convention, and returning HRESULT.
+ HRESULT error values are automatically raised as WindowsError
+ exceptions.
+ """
+ class _FuncPtr(_CFuncPtr):
+ _flags_ = _FUNCFLAG_STDCALL
+ _restype_ = HRESULT
+
+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)
+pydll = LibraryLoader(PyDLL)
+
+if _os.name in ("nt", "ce"):
+ pythonapi = PyDLL("python dll", None, _sys.dllhandle)
+elif _sys.platform == "cygwin":
+ pythonapi = PyDLL("libpython%d.%d.dll" % _sys.version_info[:2])
+else:
+ pythonapi = PyDLL(None)
+
+
+if _os.name in ("nt", "ce"):
+ windll = LibraryLoader(WinDLL)
+ oledll = LibraryLoader(OleDLL)
+
+ if _os.name == "nt":
+ GetLastError = windll.kernel32.GetLastError
+ else:
+ GetLastError = windll.coredll.GetLastError
+
+ def WinError(code=None, descr=None):
+ if code is None:
+ code = GetLastError()
+ if descr is None:
+ descr = FormatError(code).strip()
+ return WindowsError(code, descr)
+
+_pointer_type_cache[None] = c_void_p
+
+if sizeof(c_uint) == sizeof(c_void_p):
+ c_size_t = c_uint
+elif sizeof(c_ulong) == sizeof(c_void_p):
+ c_size_t = c_ulong
+
+# functions
+
+from _ctypes import _memmove_addr, _memset_addr, _string_at_addr, _cast_addr
+
+## void *memmove(void *, const void *, size_t);
+memmove = CFUNCTYPE(c_void_p, c_void_p, c_void_p, c_size_t)(_memmove_addr)
+
+## void *memset(void *, int, size_t)
+memset = CFUNCTYPE(c_void_p, c_void_p, c_int, c_size_t)(_memset_addr)
+
+def PYFUNCTYPE(restype, *argtypes):
+ class CFunctionType(_CFuncPtr):
+ _argtypes_ = argtypes
+ _restype_ = restype
+ _flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI
+ return CFunctionType
+
+_cast = PYFUNCTYPE(py_object, c_void_p, py_object, py_object)(_cast_addr)
+def cast(obj, typ):
+ return _cast(obj, obj, typ)
+
+_string_at = CFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr)
+def string_at(ptr, size=-1):
+ """string_at(addr[, size]) -> string
+
+ Return the string at addr."""
+ return _string_at(ptr, size)
+
+try:
+ from _ctypes import _wstring_at_addr
+except ImportError:
+ pass
+else:
+ _wstring_at = CFUNCTYPE(py_object, c_void_p, c_int)(_wstring_at_addr)
+ def wstring_at(ptr, size=-1):
+ """wstring_at(addr[, size]) -> string
+
+ Return the string at addr."""
+ return _wstring_at(ptr, size)
+
+
+if _os.name in ("nt", "ce"): # COM stuff
+ def DllGetClassObject(rclsid, riid, ppv):
+ try:
+ ccom = __import__("comtypes.server.inprocserver", globals(), locals(), ['*'])
+ except ImportError:
+ return -2147221231 # CLASS_E_CLASSNOTAVAILABLE
+ else:
+ return ccom.DllGetClassObject(rclsid, riid, ppv)
+
+ def DllCanUnloadNow():
+ try:
+ ccom = __import__("comtypes.server.inprocserver", globals(), locals(), ['*'])
+ except ImportError:
+ return 0 # S_OK
+ return ccom.DllCanUnloadNow()
+
+from ctypes._endian import BigEndianStructure, LittleEndianStructure
+
+# Fill in specifically-sized types
+c_int8 = c_byte
+c_uint8 = c_ubyte
+for kind in [c_short, c_int, c_long, c_longlong]:
+ if sizeof(kind) == 2: c_int16 = kind
+ elif sizeof(kind) == 4: c_int32 = kind
+ elif sizeof(kind) == 8: c_int64 = kind
+for kind in [c_ushort, c_uint, c_ulong, c_ulonglong]:
+ if sizeof(kind) == 2: c_uint16 = kind
+ elif sizeof(kind) == 4: c_uint32 = kind
+ elif sizeof(kind) == 8: c_uint64 = kind
+del(kind)
--- /dev/null
+++ b/sys/lib/python/ctypes/_endian.py
@@ -1,0 +1,60 @@
+######################################################################
+# This file should be kept compatible with Python 2.3, see PEP 291. #
+######################################################################
+import sys
+from ctypes import *
+
+_array_type = type(c_int * 3)
+
+def _other_endian(typ):
+ """Return the type with the 'other' byte order. Simple types like
+ c_int and so on already have __ctype_be__ and __ctype_le__
+ attributes which contain the types, for more complicated types
+ only arrays are supported.
+ """
+ try:
+ return getattr(typ, _OTHER_ENDIAN)
+ except AttributeError:
+ if type(typ) == _array_type:
+ return _other_endian(typ._type_) * typ._length_
+ raise TypeError("This type does not support other endian: %s" % typ)
+
+class _swapped_meta(type(Structure)):
+ def __setattr__(self, attrname, value):
+ if attrname == "_fields_":
+ fields = []
+ for desc in value:
+ name = desc[0]
+ typ = desc[1]
+ rest = desc[2:]
+ fields.append((name, _other_endian(typ)) + rest)
+ value = fields
+ super(_swapped_meta, self).__setattr__(attrname, value)
+
+################################################################
+
+# Note: The Structure metaclass checks for the *presence* (not the
+# value!) of a _swapped_bytes_ attribute to determine the bit order in
+# structures containing bit fields.
+
+if sys.byteorder == "little":
+ _OTHER_ENDIAN = "__ctype_be__"
+
+ LittleEndianStructure = Structure
+
+ class BigEndianStructure(Structure):
+ """Structure with big endian byte order"""
+ __metaclass__ = _swapped_meta
+ _swappedbytes_ = None
+
+elif sys.byteorder == "big":
+ _OTHER_ENDIAN = "__ctype_le__"
+
+ BigEndianStructure = Structure
+ class LittleEndianStructure(Structure):
+ """Structure with little endian byte order"""
+ __metaclass__ = _swapped_meta
+ _swappedbytes_ = None
+
+else:
+ raise RuntimeError("Invalid byteorder")
--- /dev/null
+++ b/sys/lib/python/ctypes/macholib/README.ctypes
@@ -1,0 +1,7 @@
+Files in this directory from from Bob Ippolito's py2app.
+
+License: Any components of the py2app suite may be distributed under
+the MIT or PSF open source licenses.
+
+This is version 1.0, SVN revision 789, from 2006/01/25.
+The main repository is http://svn.red-bean.com/bob/macholib/trunk/macholib/
\ No newline at end of file
--- /dev/null
+++ b/sys/lib/python/ctypes/macholib/__init__.py
@@ -1,0 +1,12 @@
+######################################################################
+# This file should be kept compatible with Python 2.3, see PEP 291. #
+######################################################################
+"""
+Enough Mach-O to make your head spin.
+
+See the relevant header files in /usr/include/mach-o
+
+And also Apple's documentation.
+"""
+
+__version__ = '1.0'
--- /dev/null
+++ b/sys/lib/python/ctypes/macholib/dyld.py
@@ -1,0 +1,169 @@
+######################################################################
+# This file should be kept compatible with Python 2.3, see PEP 291. #
+######################################################################
+"""
+dyld emulation
+"""
+
+import os
+from framework import framework_info
+from dylib import dylib_info
+from itertools import *
+
+__all__ = [
+ 'dyld_find', 'framework_find',
+ 'framework_info', 'dylib_info',
+]
+
+# These are the defaults as per man dyld(1)
+#
+DEFAULT_FRAMEWORK_FALLBACK = [
+ os.path.expanduser("~/Library/Frameworks"),
+ "/Library/Frameworks",
+ "/Network/Library/Frameworks",
+ "/System/Library/Frameworks",
+]
+
+DEFAULT_LIBRARY_FALLBACK = [
+ os.path.expanduser("~/lib"),
+ "/usr/local/lib",
+ "/lib",
+ "/usr/lib",
+]
+
+def ensure_utf8(s):
+ """Not all of PyObjC and Python understand unicode paths very well yet"""
+ if isinstance(s, unicode):
+ return s.encode('utf8')
+ return s
+
+def dyld_env(env, var):
+ if env is None:
+ env = os.environ
+ rval = env.get(var)
+ if rval is None:
+ return []
+ return rval.split(':')
+
+def dyld_image_suffix(env=None):
+ if env is None:
+ env = os.environ
+ return env.get('DYLD_IMAGE_SUFFIX')
+
+def dyld_framework_path(env=None):
+ return dyld_env(env, 'DYLD_FRAMEWORK_PATH')
+
+def dyld_library_path(env=None):
+ return dyld_env(env, 'DYLD_LIBRARY_PATH')
+
+def dyld_fallback_framework_path(env=None):
+ return dyld_env(env, 'DYLD_FALLBACK_FRAMEWORK_PATH')
+
+def dyld_fallback_library_path(env=None):
+ return dyld_env(env, 'DYLD_FALLBACK_LIBRARY_PATH')
+
+def dyld_image_suffix_search(iterator, env=None):
+ """For a potential path iterator, add DYLD_IMAGE_SUFFIX semantics"""
+ suffix = dyld_image_suffix(env)
+ if suffix is None:
+ return iterator
+ def _inject(iterator=iterator, suffix=suffix):
+ for path in iterator:
+ if path.endswith('.dylib'):
+ yield path[:-len('.dylib')] + suffix + '.dylib'
+ else:
+ yield path + suffix
+ yield path
+ return _inject()
+
+def dyld_override_search(name, env=None):
+ # If DYLD_FRAMEWORK_PATH is set and this dylib_name is a
+ # framework name, use the first file that exists in the framework
+ # path if any. If there is none go on to search the DYLD_LIBRARY_PATH
+ # if any.
+
+ framework = framework_info(name)
+
+ if framework is not None:
+ for path in dyld_framework_path(env):
+ yield os.path.join(path, framework['name'])
+
+ # If DYLD_LIBRARY_PATH is set then use the first file that exists
+ # in the path. If none use the original name.
+ for path in dyld_library_path(env):
+ yield os.path.join(path, os.path.basename(name))
+
+def dyld_executable_path_search(name, executable_path=None):
+ # If we haven't done any searching and found a library and the
+ # dylib_name starts with "@executable_path/" then construct the
+ # library name.
+ if name.startswith('@executable_path/') and executable_path is not None:
+ yield os.path.join(executable_path, name[len('@executable_path/'):])
+
+def dyld_default_search(name, env=None):
+ yield name
+
+ framework = framework_info(name)
+
+ if framework is not None:
+ fallback_framework_path = dyld_fallback_framework_path(env)
+ for path in fallback_framework_path:
+ yield os.path.join(path, framework['name'])
+
+ fallback_library_path = dyld_fallback_library_path(env)
+ for path in fallback_library_path:
+ yield os.path.join(path, os.path.basename(name))
+
+ if framework is not None and not fallback_framework_path:
+ for path in DEFAULT_FRAMEWORK_FALLBACK:
+ yield os.path.join(path, framework['name'])
+
+ if not fallback_library_path:
+ for path in DEFAULT_LIBRARY_FALLBACK:
+ yield os.path.join(path, os.path.basename(name))
+
+def dyld_find(name, executable_path=None, env=None):
+ """
+ Find a library or framework using dyld semantics
+ """
+ name = ensure_utf8(name)
+ executable_path = ensure_utf8(executable_path)
+ for path in dyld_image_suffix_search(chain(
+ dyld_override_search(name, env),
+ dyld_executable_path_search(name, executable_path),
+ dyld_default_search(name, env),
+ ), env):
+ if os.path.isfile(path):
+ return path
+ raise ValueError, "dylib %s could not be found" % (name,)
+
+def framework_find(fn, executable_path=None, env=None):
+ """
+ Find a framework using dyld semantics in a very loose manner.
+
+ Will take input such as:
+ Python
+ Python.framework
+ Python.framework/Versions/Current
+ """
+ try:
+ return dyld_find(fn, executable_path=executable_path, env=env)
+ except ValueError, e:
+ pass
+ fmwk_index = fn.rfind('.framework')
+ if fmwk_index == -1:
+ fmwk_index = len(fn)
+ fn += '.framework'
+ fn = os.path.join(fn, os.path.basename(fn[:fmwk_index]))
+ try:
+ return dyld_find(fn, executable_path=executable_path, env=env)
+ except ValueError:
+ raise e
+
+def test_dyld_find():
+ env = {}
+ assert dyld_find('libSystem.dylib') == '/usr/lib/libSystem.dylib'
+ assert dyld_find('System.framework/System') == '/System/Library/Frameworks/System.framework/System'
+
+if __name__ == '__main__':
+ test_dyld_find()
--- /dev/null
+++ b/sys/lib/python/ctypes/macholib/dylib.py
@@ -1,0 +1,66 @@
+######################################################################
+# This file should be kept compatible with Python 2.3, see PEP 291. #
+######################################################################
+"""
+Generic dylib path manipulation
+"""
+
+import re
+
+__all__ = ['dylib_info']
+
+DYLIB_RE = re.compile(r"""(?x)
+(?P<location>^.*)(?:^|/)
+(?P<name>
+ (?P<shortname>\w+?)
+ (?:\.(?P<version>[^._]+))?
+ (?:_(?P<suffix>[^._]+))?
+ \.dylib$
+)
+""")
+
+def dylib_info(filename):
+ """
+ A dylib name can take one of the following four forms:
+ Location/Name.SomeVersion_Suffix.dylib
+ Location/Name.SomeVersion.dylib
+ Location/Name_Suffix.dylib
+ Location/Name.dylib
+
+ returns None if not found or a mapping equivalent to:
+ dict(
+ location='Location',
+ name='Name.SomeVersion_Suffix.dylib',
+ shortname='Name',
+ version='SomeVersion',
+ suffix='Suffix',
+ )
+
+ Note that SomeVersion and Suffix are optional and may be None
+ if not present.
+ """
+ is_dylib = DYLIB_RE.match(filename)
+ if not is_dylib:
+ return None
+ return is_dylib.groupdict()
+
+
+def test_dylib_info():
+ def d(location=None, name=None, shortname=None, version=None, suffix=None):
+ return dict(
+ location=location,
+ name=name,
+ shortname=shortname,
+ version=version,
+ suffix=suffix
+ )
+ assert dylib_info('completely/invalid') is None
+ assert dylib_info('completely/invalide_debug') is None
+ assert dylib_info('P/Foo.dylib') == d('P', 'Foo.dylib', 'Foo')
+ assert dylib_info('P/Foo_debug.dylib') == d('P', 'Foo_debug.dylib', 'Foo', suffix='debug')
+ assert dylib_info('P/Foo.A.dylib') == d('P', 'Foo.A.dylib', 'Foo', 'A')
+ assert dylib_info('P/Foo_debug.A.dylib') == d('P', 'Foo_debug.A.dylib', 'Foo_debug', 'A')
+ assert dylib_info('P/Foo.A_debug.dylib') == d('P', 'Foo.A_debug.dylib', 'Foo', 'A', 'debug')
+
+if __name__ == '__main__':
+ test_dylib_info()
--- /dev/null
+++ b/sys/lib/python/ctypes/macholib/fetch_macholib
@@ -1,0 +1,2 @@
+#!/bin/sh
+svn export --force http://svn.red-bean.com/bob/macholib/trunk/macholib/ .
--- /dev/null
+++ b/sys/lib/python/ctypes/macholib/fetch_macholib.bat
@@ -1,0 +1,1 @@
+svn export --force http://svn.red-bean.com/bob/macholib/trunk/macholib/ .
--- /dev/null
+++ b/sys/lib/python/ctypes/macholib/framework.py
@@ -1,0 +1,68 @@
+######################################################################
+# This file should be kept compatible with Python 2.3, see PEP 291. #
+######################################################################
+"""
+Generic framework path manipulation
+"""
+
+import re
+
+__all__ = ['framework_info']
+
+STRICT_FRAMEWORK_RE = re.compile(r"""(?x)
+(?P<location>^.*)(?:^|/)
+(?P<name>
+ (?P<shortname>\w+).framework/
+ (?:Versions/(?P<version>[^/]+)/)?
+ (?P=shortname)
+ (?:_(?P<suffix>[^_]+))?
+)$
+""")
+
+def framework_info(filename):
+ """
+ A framework name can take one of the following four forms:
+ Location/Name.framework/Versions/SomeVersion/Name_Suffix
+ Location/Name.framework/Versions/SomeVersion/Name
+ Location/Name.framework/Name_Suffix
+ Location/Name.framework/Name
+
+ returns None if not found, or a mapping equivalent to:
+ dict(
+ location='Location',
+ name='Name.framework/Versions/SomeVersion/Name_Suffix',
+ shortname='Name',
+ version='SomeVersion',
+ suffix='Suffix',
+ )
+
+ Note that SomeVersion and Suffix are optional and may be None
+ if not present
+ """
+ is_framework = STRICT_FRAMEWORK_RE.match(filename)
+ if not is_framework:
+ return None
+ return is_framework.groupdict()
+
+def test_framework_info():
+ def d(location=None, name=None, shortname=None, version=None, suffix=None):
+ return dict(
+ location=location,
+ name=name,
+ shortname=shortname,
+ version=version,
+ suffix=suffix
+ )
+ assert framework_info('completely/invalid') is None
+ assert framework_info('completely/invalid/_debug') is None
+ assert framework_info('P/F.framework') is None
+ assert framework_info('P/F.framework/_debug') is None
+ assert framework_info('P/F.framework/F') == d('P', 'F.framework/F', 'F')
+ assert framework_info('P/F.framework/F_debug') == d('P', 'F.framework/F_debug', 'F', suffix='debug')
+ assert framework_info('P/F.framework/Versions') is None
+ assert framework_info('P/F.framework/Versions/A') is None
+ assert framework_info('P/F.framework/Versions/A/F') == d('P', 'F.framework/Versions/A/F', 'F', 'A')
+ assert framework_info('P/F.framework/Versions/A/F_debug') == d('P', 'F.framework/Versions/A/F_debug', 'F', 'A', 'debug')
+
+if __name__ == '__main__':
+ test_framework_info()
--- /dev/null
+++ b/sys/lib/python/ctypes/util.py
@@ -1,0 +1,154 @@
+######################################################################
+# This file should be kept compatible with Python 2.3, see PEP 291. #
+######################################################################
+import sys, os
+
+# find_library(name) returns the pathname of a library, or None.
+if os.name == "nt":
+ def find_library(name):
+ # See MSDN for the REAL search order.
+ for directory in os.environ['PATH'].split(os.pathsep):
+ fname = os.path.join(directory, name)
+ if os.path.exists(fname):
+ return fname
+ if fname.lower().endswith(".dll"):
+ continue
+ fname = fname + ".dll"
+ if os.path.exists(fname):
+ return fname
+ return None
+
+if os.name == "ce":
+ # search path according to MSDN:
+ # - absolute path specified by filename
+ # - The .exe launch directory
+ # - the Windows directory
+ # - ROM dll files (where are they?)
+ # - OEM specified search path: HKLM\Loader\SystemPath
+ def find_library(name):
+ return name
+
+if os.name == "posix" and sys.platform == "darwin":
+ from ctypes.macholib.dyld import dyld_find as _dyld_find
+ def find_library(name):
+ possible = ['lib%s.dylib' % name,
+ '%s.dylib' % name,
+ '%s.framework/%s' % (name, name)]
+ for name in possible:
+ try:
+ return _dyld_find(name)
+ except ValueError:
+ continue
+ return None
+
+elif os.name == "posix":
+ # Andreas Degert's find functions, using gcc, /sbin/ldconfig, objdump
+ import re, tempfile, errno
+
+ def _findLib_gcc(name):
+ expr = r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name)
+ fdout, ccout = tempfile.mkstemp()
+ os.close(fdout)
+ cmd = 'if type gcc >/dev/null 2>&1; then CC=gcc; else CC=cc; fi;' \
+ '$CC -Wl,-t -o ' + ccout + ' 2>&1 -l' + name
+ try:
+ f = os.popen(cmd)
+ trace = f.read()
+ f.close()
+ finally:
+ try:
+ os.unlink(ccout)
+ except OSError, e:
+ if e.errno != errno.ENOENT:
+ raise
+ res = re.search(expr, trace)
+ if not res:
+ return None
+ return res.group(0)
+
+ def _get_soname(f):
+ # assuming GNU binutils / ELF
+ if not f:
+ return None
+ cmd = "objdump -p -j .dynamic 2>/dev/null " + f
+ res = re.search(r'\sSONAME\s+([^\s]+)', os.popen(cmd).read())
+ if not res:
+ return None
+ return res.group(1)
+
+ if (sys.platform.startswith("freebsd")
+ or sys.platform.startswith("openbsd")
+ or sys.platform.startswith("dragonfly")):
+
+ def _num_version(libname):
+ # "libxyz.so.MAJOR.MINOR" => [ MAJOR, MINOR ]
+ parts = libname.split(".")
+ nums = []
+ try:
+ while parts:
+ nums.insert(0, int(parts.pop()))
+ except ValueError:
+ pass
+ return nums or [ sys.maxint ]
+
+ def find_library(name):
+ ename = re.escape(name)
+ expr = r':-l%s\.\S+ => \S*/(lib%s\.\S+)' % (ename, ename)
+ res = re.findall(expr,
+ os.popen('/sbin/ldconfig -r 2>/dev/null').read())
+ if not res:
+ return _get_soname(_findLib_gcc(name))
+ res.sort(cmp= lambda x,y: cmp(_num_version(x), _num_version(y)))
+ return res[-1]
+
+ else:
+
+ def _findLib_ldconfig(name):
+ # XXX assuming GLIBC's ldconfig (with option -p)
+ expr = r'/[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name)
+ res = re.search(expr,
+ os.popen('/sbin/ldconfig -p 2>/dev/null').read())
+ if not res:
+ # Hm, this works only for libs needed by the python executable.
+ cmd = 'ldd %s 2>/dev/null' % sys.executable
+ res = re.search(expr, os.popen(cmd).read())
+ if not res:
+ return None
+ return res.group(0)
+
+ def find_library(name):
+ return _get_soname(_findLib_ldconfig(name) or _findLib_gcc(name))
+
+################################################################
+# test code
+
+def test():
+ from ctypes import cdll
+ if os.name == "nt":
+ print cdll.msvcrt
+ print cdll.load("msvcrt")
+ print find_library("msvcrt")
+
+ if os.name == "posix":
+ # find and load_version
+ print find_library("m")
+ print find_library("c")
+ print find_library("bz2")
+
+ # getattr
+## print cdll.m
+## print cdll.bz2
+
+ # load
+ if sys.platform == "darwin":
+ print cdll.LoadLibrary("libm.dylib")
+ print cdll.LoadLibrary("libcrypto.dylib")
+ print cdll.LoadLibrary("libSystem.dylib")
+ print cdll.LoadLibrary("System.framework/System")
+ else:
+ print cdll.LoadLibrary("libm.so")
+ print cdll.LoadLibrary("libcrypt.so")
+ print find_library("crypt")
+
+if __name__ == "__main__":
+ test()
--- /dev/null
+++ b/sys/lib/python/ctypes/wintypes.py
@@ -1,0 +1,172 @@
+######################################################################
+# This file should be kept compatible with Python 2.3, see PEP 291. #
+######################################################################
+
+# The most useful windows datatypes
+from ctypes import *
+
+BYTE = c_byte
+WORD = c_ushort
+DWORD = c_ulong
+
+WCHAR = c_wchar
+UINT = c_uint
+
+DOUBLE = c_double
+
+BOOLEAN = BYTE
+BOOL = c_long
+
+from ctypes import _SimpleCData
+class VARIANT_BOOL(_SimpleCData):
+ _type_ = "v"
+ def __repr__(self):
+ return "%s(%r)" % (self.__class__.__name__, self.value)
+
+ULONG = c_ulong
+LONG = c_long
+
+# in the windows header files, these are structures.
+_LARGE_INTEGER = LARGE_INTEGER = c_longlong
+_ULARGE_INTEGER = ULARGE_INTEGER = c_ulonglong
+
+LPCOLESTR = LPOLESTR = OLESTR = c_wchar_p
+LPCWSTR = LPWSTR = c_wchar_p
+LPCSTR = LPSTR = c_char_p
+
+WPARAM = c_uint
+LPARAM = c_long
+
+ATOM = WORD
+LANGID = WORD
+
+COLORREF = DWORD
+LGRPID = DWORD
+LCTYPE = DWORD
+
+LCID = DWORD
+
+################################################################
+# HANDLE types
+HANDLE = c_ulong # in the header files: void *
+
+HACCEL = HANDLE
+HBITMAP = HANDLE
+HBRUSH = HANDLE
+HCOLORSPACE = HANDLE
+HDC = HANDLE
+HDESK = HANDLE
+HDWP = HANDLE
+HENHMETAFILE = HANDLE
+HFONT = HANDLE
+HGDIOBJ = HANDLE
+HGLOBAL = HANDLE
+HHOOK = HANDLE
+HICON = HANDLE
+HINSTANCE = HANDLE
+HKEY = HANDLE
+HKL = HANDLE
+HLOCAL = HANDLE
+HMENU = HANDLE
+HMETAFILE = HANDLE
+HMODULE = HANDLE
+HMONITOR = HANDLE
+HPALETTE = HANDLE
+HPEN = HANDLE
+HRGN = HANDLE
+HRSRC = HANDLE
+HSTR = HANDLE
+HTASK = HANDLE
+HWINSTA = HANDLE
+HWND = HANDLE
+SC_HANDLE = HANDLE
+SERVICE_STATUS_HANDLE = HANDLE
+
+################################################################
+# Some important structure definitions
+
+class RECT(Structure):
+ _fields_ = [("left", c_long),
+ ("top", c_long),
+ ("right", c_long),
+ ("bottom", c_long)]
+tagRECT = _RECTL = RECTL = RECT
+
+class _SMALL_RECT(Structure):
+ _fields_ = [('Left', c_short),
+ ('Top', c_short),
+ ('Right', c_short),
+ ('Bottom', c_short)]
+SMALL_RECT = _SMALL_RECT
+
+class _COORD(Structure):
+ _fields_ = [('X', c_short),
+ ('Y', c_short)]
+
+class POINT(Structure):
+ _fields_ = [("x", c_long),
+ ("y", c_long)]
+tagPOINT = _POINTL = POINTL = POINT
+
+class SIZE(Structure):
+ _fields_ = [("cx", c_long),
+ ("cy", c_long)]
+tagSIZE = SIZEL = SIZE
+
+def RGB(red, green, blue):
+ return red + (green << 8) + (blue << 16)
+
+class FILETIME(Structure):
+ _fields_ = [("dwLowDateTime", DWORD),
+ ("dwHighDateTime", DWORD)]
+_FILETIME = FILETIME
+
+class MSG(Structure):
+ _fields_ = [("hWnd", HWND),
+ ("message", c_uint),
+ ("wParam", WPARAM),
+ ("lParam", LPARAM),
+ ("time", DWORD),
+ ("pt", POINT)]
+tagMSG = MSG
+MAX_PATH = 260
+
+class WIN32_FIND_DATAA(Structure):
+ _fields_ = [("dwFileAttributes", DWORD),
+ ("ftCreationTime", FILETIME),
+ ("ftLastAccessTime", FILETIME),
+ ("ftLastWriteTime", FILETIME),
+ ("nFileSizeHigh", DWORD),
+ ("nFileSizeLow", DWORD),
+ ("dwReserved0", DWORD),
+ ("dwReserved1", DWORD),
+ ("cFileName", c_char * MAX_PATH),
+ ("cAlternameFileName", c_char * 14)]
+
+class WIN32_FIND_DATAW(Structure):
+ _fields_ = [("dwFileAttributes", DWORD),
+ ("ftCreationTime", FILETIME),
+ ("ftLastAccessTime", FILETIME),
+ ("ftLastWriteTime", FILETIME),
+ ("nFileSizeHigh", DWORD),
+ ("nFileSizeLow", DWORD),
+ ("dwReserved0", DWORD),
+ ("dwReserved1", DWORD),
+ ("cFileName", c_wchar * MAX_PATH),
+ ("cAlternameFileName", c_wchar * 14)]
+
+__all__ = ['ATOM', 'BOOL', 'BOOLEAN', 'BYTE', 'COLORREF', 'DOUBLE',
+ 'DWORD', 'FILETIME', 'HACCEL', 'HANDLE', 'HBITMAP', 'HBRUSH',
+ 'HCOLORSPACE', 'HDC', 'HDESK', 'HDWP', 'HENHMETAFILE', 'HFONT',
+ 'HGDIOBJ', 'HGLOBAL', 'HHOOK', 'HICON', 'HINSTANCE', 'HKEY',
+ 'HKL', 'HLOCAL', 'HMENU', 'HMETAFILE', 'HMODULE', 'HMONITOR',
+ 'HPALETTE', 'HPEN', 'HRGN', 'HRSRC', 'HSTR', 'HTASK', 'HWINSTA',
+ 'HWND', 'LANGID', 'LARGE_INTEGER', 'LCID', 'LCTYPE', 'LGRPID',
+ 'LONG', 'LPARAM', 'LPCOLESTR', 'LPCSTR', 'LPCWSTR', 'LPOLESTR',
+ 'LPSTR', 'LPWSTR', 'MAX_PATH', 'MSG', 'OLESTR', 'POINT',
+ 'POINTL', 'RECT', 'RECTL', 'RGB', 'SC_HANDLE',
+ 'SERVICE_STATUS_HANDLE', 'SIZE', 'SIZEL', 'SMALL_RECT', 'UINT',
+ 'ULARGE_INTEGER', 'ULONG', 'VARIANT_BOOL', 'WCHAR',
+ 'WIN32_FIND_DATAA', 'WIN32_FIND_DATAW', 'WORD', 'WPARAM', '_COORD',
+ '_FILETIME', '_LARGE_INTEGER', '_POINTL', '_RECTL', '_SMALL_RECT',
+ '_ULARGE_INTEGER', 'tagMSG', 'tagPOINT', 'tagRECT', 'tagSIZE']
--- /dev/null
+++ b/sys/lib/python/curses/__init__.py
@@ -1,0 +1,53 @@
+"""curses
+
+The main package for curses support for Python. Normally used by importing
+the package, and perhaps a particular module inside it.
+
+ import curses
+ from curses import textpad
+ curses.initwin()
+ ...
+
+"""
+
+__revision__ = "$Id: __init__.py 36560 2004-07-18 06:16:08Z tim_one $"
+
+from _curses import *
+from curses.wrapper import wrapper
+
+# Some constants, most notably the ACS_* ones, are only added to the C
+# _curses module's dictionary after initscr() is called. (Some
+# versions of SGI's curses don't define values for those constants
+# until initscr() has been called.) This wrapper function calls the
+# underlying C initscr(), and then copies the constants from the
+# _curses module to the curses package's dictionary. Don't do 'from
+# curses import *' if you'll be needing the ACS_* constants.
+
+def initscr():
+ import _curses, curses
+ stdscr = _curses.initscr()
+ for key, value in _curses.__dict__.items():
+ if key[0:4] == 'ACS_' or key in ('LINES', 'COLS'):
+ setattr(curses, key, value)
+
+ return stdscr
+
+# This is a similar wrapper for start_color(), which adds the COLORS and
+# COLOR_PAIRS variables which are only available after start_color() is
+# called.
+
+def start_color():
+ import _curses, curses
+ retval = _curses.start_color()
+ if hasattr(_curses, 'COLORS'):
+ curses.COLORS = _curses.COLORS
+ if hasattr(_curses, 'COLOR_PAIRS'):
+ curses.COLOR_PAIRS = _curses.COLOR_PAIRS
+ return retval
+
+# Import Python has_key() implementation if _curses doesn't contain has_key()
+
+try:
+ has_key
+except NameError:
+ from has_key import has_key
--- /dev/null
+++ b/sys/lib/python/curses/ascii.py
@@ -1,0 +1,99 @@
+"""Constants and membership tests for ASCII characters"""
+
+NUL = 0x00 # ^@
+SOH = 0x01 # ^A
+STX = 0x02 # ^B
+ETX = 0x03 # ^C
+EOT = 0x04 # ^D
+ENQ = 0x05 # ^E
+ACK = 0x06 # ^F
+BEL = 0x07 # ^G
+BS = 0x08 # ^H
+TAB = 0x09 # ^I
+HT = 0x09 # ^I
+LF = 0x0a # ^J
+NL = 0x0a # ^J
+VT = 0x0b # ^K
+FF = 0x0c # ^L
+CR = 0x0d # ^M
+SO = 0x0e # ^N
+SI = 0x0f # ^O
+DLE = 0x10 # ^P
+DC1 = 0x11 # ^Q
+DC2 = 0x12 # ^R
+DC3 = 0x13 # ^S
+DC4 = 0x14 # ^T
+NAK = 0x15 # ^U
+SYN = 0x16 # ^V
+ETB = 0x17 # ^W
+CAN = 0x18 # ^X
+EM = 0x19 # ^Y
+SUB = 0x1a # ^Z
+ESC = 0x1b # ^[
+FS = 0x1c # ^\
+GS = 0x1d # ^]
+RS = 0x1e # ^^
+US = 0x1f # ^_
+SP = 0x20 # space
+DEL = 0x7f # delete
+
+controlnames = [
+"NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
+"BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
+"DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
+"CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US",
+"SP"
+]
+
+def _ctoi(c):
+ if type(c) == type(""):
+ return ord(c)
+ else:
+ return c
+
+def isalnum(c): return isalpha(c) or isdigit(c)
+def isalpha(c): return isupper(c) or islower(c)
+def isascii(c): return _ctoi(c) <= 127 # ?
+def isblank(c): return _ctoi(c) in (8,32)
+def iscntrl(c): return _ctoi(c) <= 31
+def isdigit(c): return _ctoi(c) >= 48 and _ctoi(c) <= 57
+def isgraph(c): return _ctoi(c) >= 33 and _ctoi(c) <= 126
+def islower(c): return _ctoi(c) >= 97 and _ctoi(c) <= 122
+def isprint(c): return _ctoi(c) >= 32 and _ctoi(c) <= 126
+def ispunct(c): return _ctoi(c) != 32 and not isalnum(c)
+def isspace(c): return _ctoi(c) in (9, 10, 11, 12, 13, 32)
+def isupper(c): return _ctoi(c) >= 65 and _ctoi(c) <= 90
+def isxdigit(c): return isdigit(c) or \
+ (_ctoi(c) >= 65 and _ctoi(c) <= 70) or (_ctoi(c) >= 97 and _ctoi(c) <= 102)
+def isctrl(c): return _ctoi(c) < 32
+def ismeta(c): return _ctoi(c) > 127
+
+def ascii(c):
+ if type(c) == type(""):
+ return chr(_ctoi(c) & 0x7f)
+ else:
+ return _ctoi(c) & 0x7f
+
+def ctrl(c):
+ if type(c) == type(""):
+ return chr(_ctoi(c) & 0x1f)
+ else:
+ return _ctoi(c) & 0x1f
+
+def alt(c):
+ if type(c) == type(""):
+ return chr(_ctoi(c) | 0x80)
+ else:
+ return _ctoi(c) | 0x80
+
+def unctrl(c):
+ bits = _ctoi(c)
+ if bits == 0x7f:
+ rep = "^?"
+ elif isprint(bits & 0x7f):
+ rep = chr(bits & 0x7f)
+ else:
+ rep = "^" + chr(((bits & 0x7f) | 0x20) + 0x20)
+ if bits & 0x80:
+ return "!" + rep
+ return rep
--- /dev/null
+++ b/sys/lib/python/curses/has_key.py
@@ -1,0 +1,192 @@
+
+#
+# Emulation of has_key() function for platforms that don't use ncurses
+#
+
+import _curses
+
+# Table mapping curses keys to the terminfo capability name
+
+_capability_names = {
+ _curses.KEY_A1: 'ka1',
+ _curses.KEY_A3: 'ka3',
+ _curses.KEY_B2: 'kb2',
+ _curses.KEY_BACKSPACE: 'kbs',
+ _curses.KEY_BEG: 'kbeg',
+ _curses.KEY_BTAB: 'kcbt',
+ _curses.KEY_C1: 'kc1',
+ _curses.KEY_C3: 'kc3',
+ _curses.KEY_CANCEL: 'kcan',
+ _curses.KEY_CATAB: 'ktbc',
+ _curses.KEY_CLEAR: 'kclr',
+ _curses.KEY_CLOSE: 'kclo',
+ _curses.KEY_COMMAND: 'kcmd',
+ _curses.KEY_COPY: 'kcpy',
+ _curses.KEY_CREATE: 'kcrt',
+ _curses.KEY_CTAB: 'kctab',
+ _curses.KEY_DC: 'kdch1',
+ _curses.KEY_DL: 'kdl1',
+ _curses.KEY_DOWN: 'kcud1',
+ _curses.KEY_EIC: 'krmir',
+ _curses.KEY_END: 'kend',
+ _curses.KEY_ENTER: 'kent',
+ _curses.KEY_EOL: 'kel',
+ _curses.KEY_EOS: 'ked',
+ _curses.KEY_EXIT: 'kext',
+ _curses.KEY_F0: 'kf0',
+ _curses.KEY_F1: 'kf1',
+ _curses.KEY_F10: 'kf10',
+ _curses.KEY_F11: 'kf11',
+ _curses.KEY_F12: 'kf12',
+ _curses.KEY_F13: 'kf13',
+ _curses.KEY_F14: 'kf14',
+ _curses.KEY_F15: 'kf15',
+ _curses.KEY_F16: 'kf16',
+ _curses.KEY_F17: 'kf17',
+ _curses.KEY_F18: 'kf18',
+ _curses.KEY_F19: 'kf19',
+ _curses.KEY_F2: 'kf2',
+ _curses.KEY_F20: 'kf20',
+ _curses.KEY_F21: 'kf21',
+ _curses.KEY_F22: 'kf22',
+ _curses.KEY_F23: 'kf23',
+ _curses.KEY_F24: 'kf24',
+ _curses.KEY_F25: 'kf25',
+ _curses.KEY_F26: 'kf26',
+ _curses.KEY_F27: 'kf27',
+ _curses.KEY_F28: 'kf28',
+ _curses.KEY_F29: 'kf29',
+ _curses.KEY_F3: 'kf3',
+ _curses.KEY_F30: 'kf30',
+ _curses.KEY_F31: 'kf31',
+ _curses.KEY_F32: 'kf32',
+ _curses.KEY_F33: 'kf33',
+ _curses.KEY_F34: 'kf34',
+ _curses.KEY_F35: 'kf35',
+ _curses.KEY_F36: 'kf36',
+ _curses.KEY_F37: 'kf37',
+ _curses.KEY_F38: 'kf38',
+ _curses.KEY_F39: 'kf39',
+ _curses.KEY_F4: 'kf4',
+ _curses.KEY_F40: 'kf40',
+ _curses.KEY_F41: 'kf41',
+ _curses.KEY_F42: 'kf42',
+ _curses.KEY_F43: 'kf43',
+ _curses.KEY_F44: 'kf44',
+ _curses.KEY_F45: 'kf45',
+ _curses.KEY_F46: 'kf46',
+ _curses.KEY_F47: 'kf47',
+ _curses.KEY_F48: 'kf48',
+ _curses.KEY_F49: 'kf49',
+ _curses.KEY_F5: 'kf5',
+ _curses.KEY_F50: 'kf50',
+ _curses.KEY_F51: 'kf51',
+ _curses.KEY_F52: 'kf52',
+ _curses.KEY_F53: 'kf53',
+ _curses.KEY_F54: 'kf54',
+ _curses.KEY_F55: 'kf55',
+ _curses.KEY_F56: 'kf56',
+ _curses.KEY_F57: 'kf57',
+ _curses.KEY_F58: 'kf58',
+ _curses.KEY_F59: 'kf59',
+ _curses.KEY_F6: 'kf6',
+ _curses.KEY_F60: 'kf60',
+ _curses.KEY_F61: 'kf61',
+ _curses.KEY_F62: 'kf62',
+ _curses.KEY_F63: 'kf63',
+ _curses.KEY_F7: 'kf7',
+ _curses.KEY_F8: 'kf8',
+ _curses.KEY_F9: 'kf9',
+ _curses.KEY_FIND: 'kfnd',
+ _curses.KEY_HELP: 'khlp',
+ _curses.KEY_HOME: 'khome',
+ _curses.KEY_IC: 'kich1',
+ _curses.KEY_IL: 'kil1',
+ _curses.KEY_LEFT: 'kcub1',
+ _curses.KEY_LL: 'kll',
+ _curses.KEY_MARK: 'kmrk',
+ _curses.KEY_MESSAGE: 'kmsg',
+ _curses.KEY_MOVE: 'kmov',
+ _curses.KEY_NEXT: 'knxt',
+ _curses.KEY_NPAGE: 'knp',
+ _curses.KEY_OPEN: 'kopn',
+ _curses.KEY_OPTIONS: 'kopt',
+ _curses.KEY_PPAGE: 'kpp',
+ _curses.KEY_PREVIOUS: 'kprv',
+ _curses.KEY_PRINT: 'kprt',
+ _curses.KEY_REDO: 'krdo',
+ _curses.KEY_REFERENCE: 'kref',
+ _curses.KEY_REFRESH: 'krfr',
+ _curses.KEY_REPLACE: 'krpl',
+ _curses.KEY_RESTART: 'krst',
+ _curses.KEY_RESUME: 'kres',
+ _curses.KEY_RIGHT: 'kcuf1',
+ _curses.KEY_SAVE: 'ksav',
+ _curses.KEY_SBEG: 'kBEG',
+ _curses.KEY_SCANCEL: 'kCAN',
+ _curses.KEY_SCOMMAND: 'kCMD',
+ _curses.KEY_SCOPY: 'kCPY',
+ _curses.KEY_SCREATE: 'kCRT',
+ _curses.KEY_SDC: 'kDC',
+ _curses.KEY_SDL: 'kDL',
+ _curses.KEY_SELECT: 'kslt',
+ _curses.KEY_SEND: 'kEND',
+ _curses.KEY_SEOL: 'kEOL',
+ _curses.KEY_SEXIT: 'kEXT',
+ _curses.KEY_SF: 'kind',
+ _curses.KEY_SFIND: 'kFND',
+ _curses.KEY_SHELP: 'kHLP',
+ _curses.KEY_SHOME: 'kHOM',
+ _curses.KEY_SIC: 'kIC',
+ _curses.KEY_SLEFT: 'kLFT',
+ _curses.KEY_SMESSAGE: 'kMSG',
+ _curses.KEY_SMOVE: 'kMOV',
+ _curses.KEY_SNEXT: 'kNXT',
+ _curses.KEY_SOPTIONS: 'kOPT',
+ _curses.KEY_SPREVIOUS: 'kPRV',
+ _curses.KEY_SPRINT: 'kPRT',
+ _curses.KEY_SR: 'kri',
+ _curses.KEY_SREDO: 'kRDO',
+ _curses.KEY_SREPLACE: 'kRPL',
+ _curses.KEY_SRIGHT: 'kRIT',
+ _curses.KEY_SRSUME: 'kRES',
+ _curses.KEY_SSAVE: 'kSAV',
+ _curses.KEY_SSUSPEND: 'kSPD',
+ _curses.KEY_STAB: 'khts',
+ _curses.KEY_SUNDO: 'kUND',
+ _curses.KEY_SUSPEND: 'kspd',
+ _curses.KEY_UNDO: 'kund',
+ _curses.KEY_UP: 'kcuu1'
+ }
+
+def has_key(ch):
+ if isinstance(ch, str):
+ ch = ord(ch)
+
+ # Figure out the correct capability name for the keycode.
+ capability_name = _capability_names.get(ch)
+ if capability_name is None:
+ return False
+
+ #Check the current terminal description for that capability;
+ #if present, return true, else return false.
+ if _curses.tigetstr( capability_name ):
+ return True
+ else:
+ return False
+
+if __name__ == '__main__':
+ # Compare the output of this implementation and the ncurses has_key,
+ # on platforms where has_key is already available
+ try:
+ L = []
+ _curses.initscr()
+ for key in _capability_names.keys():
+ system = _curses.has_key(key)
+ python = has_key(key)
+ if system != python:
+ L.append( 'Mismatch for key %s, system=%i, Python=%i'
+ % (_curses.keyname( key ), system, python) )
+ finally:
+ _curses.endwin()
+ for i in L: print i
--- /dev/null
+++ b/sys/lib/python/curses/panel.py
@@ -1,0 +1,8 @@
+"""curses.panel
+
+Module for using panels with curses.
+"""
+
+__revision__ = "$Id: panel.py 36560 2004-07-18 06:16:08Z tim_one $"
+
+from _curses_panel import *
--- /dev/null
+++ b/sys/lib/python/curses/textpad.py
@@ -1,0 +1,173 @@
+"""Simple textbox editing widget with Emacs-like keybindings."""
+
+import curses, ascii
+
+def rectangle(win, uly, ulx, lry, lrx):
+ """Draw a rectangle with corners at the provided upper-left
+ and lower-right coordinates.
+ """
+ win.vline(uly+1, ulx, curses.ACS_VLINE, lry - uly - 1)
+ win.hline(uly, ulx+1, curses.ACS_HLINE, lrx - ulx - 1)
+ win.hline(lry, ulx+1, curses.ACS_HLINE, lrx - ulx - 1)
+ win.vline(uly+1, lrx, curses.ACS_VLINE, lry - uly - 1)
+ win.addch(uly, ulx, curses.ACS_ULCORNER)
+ win.addch(uly, lrx, curses.ACS_URCORNER)
+ win.addch(lry, lrx, curses.ACS_LRCORNER)
+ win.addch(lry, ulx, curses.ACS_LLCORNER)
+
+class Textbox:
+ """Editing widget using the interior of a window object.
+ Supports the following Emacs-like key bindings:
+
+ Ctrl-A Go to left edge of window.
+ Ctrl-B Cursor left, wrapping to previous line if appropriate.
+ Ctrl-D Delete character under cursor.
+ Ctrl-E Go to right edge (stripspaces off) or end of line (stripspaces on).
+ Ctrl-F Cursor right, wrapping to next line when appropriate.
+ Ctrl-G Terminate, returning the window contents.
+ Ctrl-H Delete character backward.
+ Ctrl-J Terminate if the window is 1 line, otherwise insert newline.
+ Ctrl-K If line is blank, delete it, otherwise clear to end of line.
+ Ctrl-L Refresh screen.
+ Ctrl-N Cursor down; move down one line.
+ Ctrl-O Insert a blank line at cursor location.
+ Ctrl-P Cursor up; move up one line.
+
+ Move operations do nothing if the cursor is at an edge where the movement
+ is not possible. The following synonyms are supported where possible:
+
+ KEY_LEFT = Ctrl-B, KEY_RIGHT = Ctrl-F, KEY_UP = Ctrl-P, KEY_DOWN = Ctrl-N
+ KEY_BACKSPACE = Ctrl-h
+ """
+ def __init__(self, win):
+ self.win = win
+ (self.maxy, self.maxx) = win.getmaxyx()
+ self.maxy = self.maxy - 1
+ self.maxx = self.maxx - 1
+ self.stripspaces = 1
+ self.lastcmd = None
+ win.keypad(1)
+
+ def _end_of_line(self, y):
+ "Go to the location of the first blank on the given line."
+ last = self.maxx
+ while 1:
+ if ascii.ascii(self.win.inch(y, last)) != ascii.SP:
+ last = min(self.maxx, last+1)
+ break
+ elif last == 0:
+ break
+ last = last - 1
+ return last
+
+ def do_command(self, ch):
+ "Process a single editing command."
+ (y, x) = self.win.getyx()
+ self.lastcmd = ch
+ if ascii.isprint(ch):
+ if y < self.maxy or x < self.maxx:
+ # The try-catch ignores the error we trigger from some curses
+ # versions by trying to write into the lowest-rightmost spot
+ # in the window.
+ try:
+ self.win.addch(ch)
+ except curses.error:
+ pass
+ elif ch == ascii.SOH: # ^a
+ self.win.move(y, 0)
+ elif ch in (ascii.STX,curses.KEY_LEFT, ascii.BS,curses.KEY_BACKSPACE):
+ if x > 0:
+ self.win.move(y, x-1)
+ elif y == 0:
+ pass
+ elif self.stripspaces:
+ self.win.move(y-1, self._end_of_line(y-1))
+ else:
+ self.win.move(y-1, self.maxx)
+ if ch in (ascii.BS, curses.KEY_BACKSPACE):
+ self.win.delch()
+ elif ch == ascii.EOT: # ^d
+ self.win.delch()
+ elif ch == ascii.ENQ: # ^e
+ if self.stripspaces:
+ self.win.move(y, self._end_of_line(y))
+ else:
+ self.win.move(y, self.maxx)
+ elif ch in (ascii.ACK, curses.KEY_RIGHT): # ^f
+ if x < self.maxx:
+ self.win.move(y, x+1)
+ elif y == self.maxy:
+ pass
+ else:
+ self.win.move(y+1, 0)
+ elif ch == ascii.BEL: # ^g
+ return 0
+ elif ch == ascii.NL: # ^j
+ if self.maxy == 0:
+ return 0
+ elif y < self.maxy:
+ self.win.move(y+1, 0)
+ elif ch == ascii.VT: # ^k
+ if x == 0 and self._end_of_line(y) == 0:
+ self.win.deleteln()
+ else:
+ # first undo the effect of self._end_of_line
+ self.win.move(y, x)
+ self.win.clrtoeol()
+ elif ch == ascii.FF: # ^l
+ self.win.refresh()
+ elif ch in (ascii.SO, curses.KEY_DOWN): # ^n
+ if y < self.maxy:
+ self.win.move(y+1, x)
+ if x > self._end_of_line(y+1):
+ self.win.move(y+1, self._end_of_line(y+1))
+ elif ch == ascii.SI: # ^o
+ self.win.insertln()
+ elif ch in (ascii.DLE, curses.KEY_UP): # ^p
+ if y > 0:
+ self.win.move(y-1, x)
+ if x > self._end_of_line(y-1):
+ self.win.move(y-1, self._end_of_line(y-1))
+ return 1
+
+ def gather(self):
+ "Collect and return the contents of the window."
+ result = ""
+ for y in range(self.maxy+1):
+ self.win.move(y, 0)
+ stop = self._end_of_line(y)
+ if stop == 0 and self.stripspaces:
+ continue
+ for x in range(self.maxx+1):
+ if self.stripspaces and x == stop:
+ break
+ result = result + chr(ascii.ascii(self.win.inch(y, x)))
+ if self.maxy > 0:
+ result = result + "\n"
+ return result
+
+ def edit(self, validate=None):
+ "Edit in the widget window and collect the results."
+ while 1:
+ ch = self.win.getch()
+ if validate:
+ ch = validate(ch)
+ if not ch:
+ continue
+ if not self.do_command(ch):
+ break
+ self.win.refresh()
+ return self.gather()
+
+if __name__ == '__main__':
+ def test_editbox(stdscr):
+ ncols, nlines = 9, 4
+ uly, ulx = 15, 20
+ stdscr.addstr(uly-2, ulx, "Use Ctrl-G to end editing.")
+ win = curses.newwin(nlines, ncols, uly, ulx)
+ rectangle(stdscr, uly-1, ulx-1, uly + nlines, ulx + ncols)
+ stdscr.refresh()
+ return Textbox(win).edit()
+
+ str = curses.wrapper(test_editbox)
+ print 'Contents of text box:', repr(str)
--- /dev/null
+++ b/sys/lib/python/curses/wrapper.py
@@ -1,0 +1,50 @@
+"""curses.wrapper
+
+Contains one function, wrapper(), which runs another function which
+should be the rest of your curses-based application. If the
+application raises an exception, wrapper() will restore the terminal
+to a sane state so you can read the resulting traceback.
+
+"""
+
+import sys, curses
+
+def wrapper(func, *args, **kwds):
+ """Wrapper function that initializes curses and calls another function,
+ restoring normal keyboard/screen behavior on error.
+ The callable object 'func' is then passed the main window 'stdscr'
+ as its first argument, followed by any other arguments passed to
+ wrapper().
+ """
+
+ res = None
+ try:
+ # Initialize curses
+ stdscr=curses.initscr()
+
+ # Turn off echoing of keys, and enter cbreak mode,
+ # where no buffering is performed on keyboard input
+ curses.noecho()
+ curses.cbreak()
+
+ # In keypad mode, escape sequences for special keys
+ # (like the cursor keys) will be interpreted and
+ # a special value like curses.KEY_LEFT will be returned
+ stdscr.keypad(1)
+
+ # Start color, too. Harmless if the terminal doesn't have
+ # color; user can test with has_color() later on. The try/catch
+ # works around a minor bit of over-conscientiousness in the curses
+ # module -- the error return from C start_color() is ignorable.
+ try:
+ curses.start_color()
+ except:
+ pass
+
+ return func(stdscr, *args, **kwds)
+ finally:
+ # Set everything back to normal
+ stdscr.keypad(0)
+ curses.echo()
+ curses.nocbreak()
+ curses.endwin()
--- /dev/null
+++ b/sys/lib/python/dbhash.py
@@ -1,0 +1,16 @@
+"""Provide a (g)dbm-compatible interface to bsddb.hashopen."""
+
+import sys
+try:
+ import bsddb
+except ImportError:
+ # prevent a second import of this module from spuriously succeeding
+ del sys.modules[__name__]
+ raise
+
+__all__ = ["error","open"]
+
+error = bsddb.error # Exported for anydbm
+
+def open(file, flag = 'r', mode=0666):
+ return bsddb.hashopen(file, flag, mode)
--- /dev/null
+++ b/sys/lib/python/decimal.py
@@ -1,0 +1,3137 @@
+# 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 the module is to support arithmetic using familiar
+"schoolhouse" rules and to avoid the some of 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',
+
+ # Functions for manipulating contexts
+ 'setcontext', 'getcontext', 'localcontext'
+]
+
+import copy as _copy
+
+#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'
+
+#Rounding decision (not part of the public API)
+NEVER_ROUND = 'NEVER_ROUND' # Round in division (non-divmod), sqrt ONLY
+ALWAYS_ROUND = 'ALWAYS_ROUND' # Every operation rounds at end.
+
+#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 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
+ """
+ def handle(self, context, *args):
+ if args:
+ if args[0] == 1: #sNaN, must drop 's' but keep diagnostics
+ return Decimal( (args[1]._sign, args[1]._int, 'n') )
+ 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 (0, (0,), 'n') #Passed to something which uses a tuple.
+
+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, double = None, *args):
+ if double is not None:
+ return (Infsign[sign],)*2
+ return Infsign[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, 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, tup=None, *args):
+ if tup is not None:
+ return (NaN, NaN) #for 0 %0, 0 // 0
+ 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.
+ """
+ pass
+
+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.
+ """
+ pass
+
+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.
+ """
+ pass
+
+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 Infsign[sign]
+ if sign == 0:
+ if context.rounding == ROUND_CEILING:
+ return Infsign[sign]
+ return Decimal((sign, (9,)*context.prec,
+ context.Emax-context.prec+1))
+ if sign == 1:
+ if context.rounding == ROUND_FLOOR:
+ return Infsign[sign]
+ return Decimal( (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:
+ def local(self, sys=sys):
+ return sys.modules[__name__]
+ threading = MockThreading()
+ del sys, MockThreading
+
+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
+
+ """
+ # The string below can't be included in the docstring until Python 2.6
+ # as the doctest module doesn't understand __future__ statements
+ """
+ >>> from __future__ import with_statement
+ >>> 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 input (sign, digit_tuple, exponent)
+ Decimal("3.14")
+ >>> Decimal(314) # int or long
+ Decimal("314")
+ >>> Decimal(Decimal(314)) # another decimal instance
+ Decimal("314")
+ """
+
+ self = object.__new__(cls)
+ self._is_special = False
+
+ # From an internal working value
+ if isinstance(value, _WorkRep):
+ self._sign = value.sign
+ self._int = tuple(map(int, str(value.int)))
+ self._exp = int(value.exp)
+ 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 integer
+ if isinstance(value, (int,long)):
+ if value >= 0:
+ self._sign = 0
+ else:
+ self._sign = 1
+ self._exp = 0
+ self._int = tuple(map(int, str(abs(value))))
+ return self
+
+ # tuple/list conversion (possibly from as_tuple())
+ if isinstance(value, (list,tuple)):
+ if len(value) != 3:
+ raise ValueError, 'Invalid arguments'
+ if value[0] not in (0,1):
+ raise ValueError, 'Invalid sign'
+ for digit in value[1]:
+ if not isinstance(digit, (int,long)) or digit < 0:
+ raise ValueError, "The second value in the tuple must be composed of non negative integer elements."
+
+ self._sign = value[0]
+ self._int = tuple(value[1])
+ if value[2] in ('F','n','N'):
+ self._exp = value[2]
+ self._is_special = True
+ else:
+ self._exp = int(value[2])
+ return self
+
+ if isinstance(value, float):
+ raise TypeError("Cannot convert float to Decimal. " +
+ "First convert the float to a string")
+
+ # Other argument types may require the context during interpretation
+ if context is None:
+ context = getcontext()
+
+ # From a string
+ # REs insist on real strings, so we can too.
+ if isinstance(value, basestring):
+ if _isinfinity(value):
+ self._exp = 'F'
+ self._int = (0,)
+ self._is_special = True
+ if _isinfinity(value) == 1:
+ self._sign = 0
+ else:
+ self._sign = 1
+ return self
+ if _isnan(value):
+ sig, sign, diag = _isnan(value)
+ self._is_special = True
+ if len(diag) > context.prec: #Diagnostic info too long
+ self._sign, self._int, self._exp = \
+ context._raise_error(ConversionSyntax)
+ return self
+ if sig == 1:
+ self._exp = 'n' #qNaN
+ else: #sig == 2
+ self._exp = 'N' #sNaN
+ self._sign = sign
+ self._int = tuple(map(int, diag)) #Diagnostic info
+ return self
+ try:
+ self._sign, self._int, self._exp = _string2exact(value)
+ except ValueError:
+ self._is_special = True
+ self._sign, self._int, self._exp = context._raise_error(ConversionSyntax)
+ return self
+
+ raise TypeError("Cannot convert %r to Decimal" % value)
+
+ 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',
+ 1, self)
+ if other_is_nan == 2:
+ return context._raise_error(InvalidOperation, 'sNaN',
+ 1, other)
+ if self_is_nan:
+ return self
+
+ return other
+ return 0
+
+ def __nonzero__(self):
+ """Is the number non-zero?
+
+ 0 if self == 0
+ 1 if self != 0
+ """
+ if self._is_special:
+ return 1
+ return sum(self._int) != 0
+
+ def __cmp__(self, other, context=None):
+ other = _convert_other(other)
+ if other is NotImplemented:
+ return other
+
+ if self._is_special or other._is_special:
+ ans = self._check_nans(other, context)
+ if ans:
+ return 1 # Comparison involving NaN's always reports self > other
+
+ # INF = INF
+ return cmp(self._isinfinity(), other._isinfinity())
+
+ if not self and not other:
+ return 0 #If both 0, sign comparison isn't certain.
+
+ #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 and \
+ self._int + (0,)*(self._exp - other._exp) == \
+ other._int + (0,)*(other._exp - self._exp):
+ return 0 #equal, except in precision. ([0]*(-x) = [])
+ elif self_adjusted > other_adjusted and self._int[0] != 0:
+ return (-1)**self._sign
+ elif self_adjusted < other_adjusted and other._int[0] != 0:
+ return -((-1)**self._sign)
+
+ # Need to round, so make sure we have a valid context
+ if context is None:
+ context = getcontext()
+
+ context = context._shallow_copy()
+ rounding = context._set_rounding(ROUND_UP) #round away from 0
+
+ flags = context._ignore_all_flags()
+ res = self.__sub__(other, context=context)
+
+ context._regard_flags(*flags)
+
+ context.rounding = rounding
+
+ if not res:
+ return 0
+ elif res._sign:
+ return -1
+ return 1
+
+ def __eq__(self, other):
+ if not isinstance(other, (Decimal, int, long)):
+ return NotImplemented
+ return self.__cmp__(other) == 0
+
+ def __ne__(self, other):
+ if not isinstance(other, (Decimal, int, long)):
+ return NotImplemented
+ 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)
+ if other is NotImplemented:
+ return other
+
+ #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, context))
+
+ def __hash__(self):
+ """x.__hash__() <==> hash(x)"""
+ # Decimal integers must hash the same as the ints
+ # Non-integer decimals are normalized and hashed as strings
+ # Normalization assures that hash(100E-1) == hash(10)
+ if self._is_special:
+ if self._isnan():
+ raise TypeError('Cannot hash a NaN value.')
+ return hash(str(self))
+ i = int(self)
+ if self == Decimal(i):
+ return hash(i)
+ assert self.__nonzero__() # '-0' handled by integer case
+ return hash(str(self.normalize()))
+
+ def as_tuple(self):
+ """Represents the number as a triple tuple.
+
+ To show the internals exactly as they are.
+ """
+ return (self._sign, 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 = 0, context=None):
+ """Return string representation of the number in scientific notation.
+
+ Captures all of the information in the underlying representation.
+ """
+
+ if self._is_special:
+ if self._isnan():
+ minus = '-'*self._sign
+ if self._int == (0,):
+ info = ''
+ else:
+ info = ''.join(map(str, self._int))
+ if self._isnan() == 2:
+ return minus + 'sNaN' + info
+ return minus + 'NaN' + info
+ if self._isinfinity():
+ minus = '-'*self._sign
+ return minus + 'Infinity'
+
+ if context is None:
+ context = getcontext()
+
+ tmp = map(str, self._int)
+ numdigits = len(self._int)
+ leftdigits = self._exp + numdigits
+ if eng and not self: #self = 0eX wants 0[.0[0]]eY, not [[0]0]0eY
+ if self._exp < 0 and self._exp >= -6: #short, no need for e/E
+ s = '-'*self._sign + '0.' + '0'*(abs(self._exp))
+ return s
+ #exp is closest mult. of 3 >= self._exp
+ exp = ((self._exp - 1)// 3 + 1) * 3
+ if exp != self._exp:
+ s = '0.'+'0'*(exp - self._exp)
+ else:
+ s = '0'
+ if exp != 0:
+ if context.capitals:
+ s += 'E'
+ else:
+ s += 'e'
+ if exp > 0:
+ s += '+' #0.0e+3, not 0.0e3
+ s += str(exp)
+ s = '-'*self._sign + s
+ return s
+ if eng:
+ dotplace = (leftdigits-1)%3+1
+ adjexp = leftdigits -1 - (leftdigits-1)%3
+ else:
+ adjexp = leftdigits-1
+ dotplace = 1
+ if self._exp == 0:
+ pass
+ elif self._exp < 0 and adjexp >= 0:
+ tmp.insert(leftdigits, '.')
+ elif self._exp < 0 and adjexp >= -6:
+ tmp[0:0] = ['0'] * int(-leftdigits)
+ tmp.insert(0, '0.')
+ else:
+ if numdigits > dotplace:
+ tmp.insert(dotplace, '.')
+ elif numdigits < dotplace:
+ tmp.extend(['0']*(dotplace-numdigits))
+ if adjexp:
+ if not context.capitals:
+ tmp.append('e')
+ else:
+ tmp.append('E')
+ if adjexp > 0:
+ tmp.append('+')
+ tmp.append(str(adjexp))
+ if eng:
+ while tmp[0:1] == ['0']:
+ tmp[0:1] = []
+ if len(tmp) == 0 or tmp[0] == '.' or tmp[0].lower() == 'e':
+ tmp[0:0] = ['0']
+ if self._sign:
+ tmp.insert(0, '-')
+
+ return ''.join(tmp)
+
+ 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=1, 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')
+ sign = 0
+ elif self._sign:
+ sign = 0
+ else:
+ sign = 1
+
+ if context is None:
+ context = getcontext()
+ if context._rounding_decision == ALWAYS_ROUND:
+ return Decimal((sign, self._int, self._exp))._fix(context)
+ return Decimal( (sign, self._int, self._exp))
+
+ 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
+
+ sign = self._sign
+ if not self:
+ # + (-0) = 0
+ sign = 0
+
+ if context is None:
+ context = getcontext()
+
+ if context._rounding_decision == ALWAYS_ROUND:
+ ans = self._fix(context)
+ else:
+ ans = Decimal(self)
+ ans._sign = sign
+ return ans
+
+ def __abs__(self, round=1, context=None):
+ """Returns the absolute value of self.
+
+ If the second argument is 0, do not round.
+ """
+ if self._is_special:
+ ans = self._check_nans(context=context)
+ if ans:
+ return ans
+
+ if not round:
+ if context is None:
+ context = getcontext()
+ context = context._shallow_copy()
+ context._set_rounding_decision(NEVER_ROUND)
+
+ 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
+
+ shouldround = context._rounding_decision == ALWAYS_ROUND
+
+ 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
+ return Decimal( (sign, (0,), exp))
+ if not self:
+ exp = max(exp, other._exp - context.prec-1)
+ ans = other._rescale(exp, watchexp=0, context=context)
+ if shouldround:
+ ans = ans._fix(context)
+ return ans
+ if not other:
+ exp = max(exp, self._exp - context.prec-1)
+ ans = self._rescale(exp, watchexp=0, context=context)
+ if shouldround:
+ ans = ans._fix(context)
+ return ans
+
+ op1 = _WorkRep(self)
+ op2 = _WorkRep(other)
+ op1, op2 = _normalize(op1, op2, shouldround, context.prec)
+
+ result = _WorkRep()
+ if op1.sign != op2.sign:
+ # Equal and opposite
+ if op1.int == op2.int:
+ if exp < context.Etiny():
+ exp = context.Etiny()
+ context._raise_error(Clamped)
+ return Decimal((negativezero, (0,), exp))
+ 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)
+ if shouldround:
+ 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
+
+ # -Decimal(0) = Decimal(0), which we don't want since
+ # (-0 - 0 = -0 + (-0) = -0, but -0 + 0 = 0.)
+ # so we change the sign directly to a copy
+ tmp = Decimal(other)
+ tmp._sign = 1-tmp._sign
+
+ return self.__add__(tmp, context=context)
+
+ def __rsub__(self, other, context=None):
+ """Return other + (-self)"""
+ other = _convert_other(other)
+ if other is NotImplemented:
+ return other
+
+ tmp = Decimal(self)
+ tmp._sign = 1 - tmp._sign
+ return other.__add__(tmp, context=context)
+
+ def _increment(self, round=1, context=None):
+ """Special case of add, adding 1eExponent
+
+ Since it is common, (rounding, for example) this adds
+ (sign)*one E self._exp to the number more efficiently than add.
+
+ For example:
+ Decimal('5.624e10')._increment() == Decimal('5.625e10')
+ """
+ if self._is_special:
+ ans = self._check_nans(context=context)
+ if ans:
+ return ans
+
+ return Decimal(self) # Must be infinite, and incrementing makes no difference
+
+ L = list(self._int)
+ L[-1] += 1
+ spot = len(L)-1
+ while L[spot] == 10:
+ L[spot] = 0
+ if spot == 0:
+ L[0:0] = [1]
+ break
+ L[spot-1] += 1
+ spot -= 1
+ ans = Decimal((self._sign, L, self._exp))
+
+ if context is None:
+ context = getcontext()
+ if round and context._rounding_decision == ALWAYS_ROUND:
+ ans = ans._fix(context)
+ return ans
+
+ 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 Infsign[resultsign]
+
+ if other._isinfinity():
+ if not self:
+ return context._raise_error(InvalidOperation, '0 * (+-)INF')
+ return Infsign[resultsign]
+
+ resultexp = self._exp + other._exp
+ shouldround = context._rounding_decision == ALWAYS_ROUND
+
+ # Special case for multiplying by zero
+ if not self or not other:
+ ans = Decimal((resultsign, (0,), resultexp))
+ if shouldround:
+ #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 = Decimal((resultsign, other._int, resultexp))
+ if shouldround:
+ ans = ans._fix(context)
+ return ans
+ if other._int == (1,):
+ ans = Decimal((resultsign, self._int, resultexp))
+ if shouldround:
+ ans = ans._fix(context)
+ return ans
+
+ op1 = _WorkRep(self)
+ op2 = _WorkRep(other)
+
+ ans = Decimal( (resultsign, map(int, str(op1.int * op2.int)), resultexp))
+ if shouldround:
+ ans = ans._fix(context)
+
+ return ans
+ __rmul__ = __mul__
+
+ def __div__(self, other, context=None):
+ """Return self / other."""
+ return self._divide(other, context=context)
+ __truediv__ = __div__
+
+ def _divide(self, other, divmod = 0, context=None):
+ """Return a / b, to context.prec precision.
+
+ divmod:
+ 0 => true division
+ 1 => (a //b, a%b)
+ 2 => a //b
+ 3 => a%b
+
+ Actually, if divmod is 2 or 3 a tuple is returned, but errors for
+ computing the other value are not raised.
+ """
+ other = _convert_other(other)
+ if other is NotImplemented:
+ if divmod in (0, 1):
+ return NotImplemented
+ return (NotImplemented, 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:
+ if divmod:
+ return (ans, ans)
+ return ans
+
+ if self._isinfinity() and other._isinfinity():
+ if divmod:
+ return (context._raise_error(InvalidOperation,
+ '(+-)INF // (+-)INF'),
+ context._raise_error(InvalidOperation,
+ '(+-)INF % (+-)INF'))
+ return context._raise_error(InvalidOperation, '(+-)INF/(+-)INF')
+
+ if self._isinfinity():
+ if divmod == 1:
+ return (Infsign[sign],
+ context._raise_error(InvalidOperation, 'INF % x'))
+ elif divmod == 2:
+ return (Infsign[sign], NaN)
+ elif divmod == 3:
+ return (Infsign[sign],
+ context._raise_error(InvalidOperation, 'INF % x'))
+ return Infsign[sign]
+
+ if other._isinfinity():
+ if divmod:
+ return (Decimal((sign, (0,), 0)), Decimal(self))
+ context._raise_error(Clamped, 'Division by infinity')
+ return Decimal((sign, (0,), context.Etiny()))
+
+ # Special cases for zeroes
+ if not self and not other:
+ if divmod:
+ return context._raise_error(DivisionUndefined, '0 / 0', 1)
+ return context._raise_error(DivisionUndefined, '0 / 0')
+
+ if not self:
+ if divmod:
+ otherside = Decimal(self)
+ otherside._exp = min(self._exp, other._exp)
+ return (Decimal((sign, (0,), 0)), otherside)
+ exp = self._exp - other._exp
+ if exp < context.Etiny():
+ exp = context.Etiny()
+ context._raise_error(Clamped, '0e-x / y')
+ if exp > context.Emax:
+ exp = context.Emax
+ context._raise_error(Clamped, '0e+x / y')
+ return Decimal( (sign, (0,), exp) )
+
+ if not other:
+ if divmod:
+ return context._raise_error(DivisionByZero, 'divmod(x,0)',
+ sign, 1)
+ return context._raise_error(DivisionByZero, 'x / 0', sign)
+
+ #OK, so neither = 0, INF or NaN
+
+ shouldround = context._rounding_decision == ALWAYS_ROUND
+
+ #If we're dividing into ints, and self < other, stop.
+ #self.__abs__(0) does not round.
+ if divmod and (self.__abs__(0, context) < other.__abs__(0, context)):
+
+ if divmod == 1 or divmod == 3:
+ exp = min(self._exp, other._exp)
+ ans2 = self._rescale(exp, context=context, watchexp=0)
+ if shouldround:
+ ans2 = ans2._fix(context)
+ return (Decimal( (sign, (0,), 0) ),
+ ans2)
+
+ elif divmod == 2:
+ #Don't round the mod part, if we don't need it.
+ return (Decimal( (sign, (0,), 0) ), Decimal(self))
+
+ op1 = _WorkRep(self)
+ op2 = _WorkRep(other)
+ op1, op2, adjust = _adjust_coefficients(op1, op2)
+ res = _WorkRep( (sign, 0, (op1.exp - op2.exp)) )
+ if divmod and res.exp > context.prec + 1:
+ return context._raise_error(DivisionImpossible)
+
+ prec_limit = 10 ** context.prec
+ while 1:
+ while op2.int <= op1.int:
+ res.int += 1
+ op1.int -= op2.int
+ if res.exp == 0 and divmod:
+ if res.int >= prec_limit and shouldround:
+ return context._raise_error(DivisionImpossible)
+ otherside = Decimal(op1)
+ frozen = context._ignore_all_flags()
+
+ exp = min(self._exp, other._exp)
+ otherside = otherside._rescale(exp, context=context, watchexp=0)
+ context._regard_flags(*frozen)
+ if shouldround:
+ otherside = otherside._fix(context)
+ return (Decimal(res), otherside)
+
+ if op1.int == 0 and adjust >= 0 and not divmod:
+ break
+ if res.int >= prec_limit and shouldround:
+ if divmod:
+ return context._raise_error(DivisionImpossible)
+ shouldround=1
+ # Really, the answer is a bit higher, so adding a one to
+ # the end will make sure the rounding is right.
+ if op1.int != 0:
+ res.int *= 10
+ res.int += 1
+ res.exp -= 1
+
+ break
+ res.int *= 10
+ res.exp -= 1
+ adjust += 1
+ op1.int *= 10
+ op1.exp -= 1
+
+ if res.exp == 0 and divmod and op2.int > op1.int:
+ #Solves an error in precision. Same as a previous block.
+
+ if res.int >= prec_limit and shouldround:
+ return context._raise_error(DivisionImpossible)
+ otherside = Decimal(op1)
+ frozen = context._ignore_all_flags()
+
+ exp = min(self._exp, other._exp)
+ otherside = otherside._rescale(exp, context=context)
+
+ context._regard_flags(*frozen)
+
+ return (Decimal(res), otherside)
+
+ ans = Decimal(res)
+ if shouldround:
+ ans = ans._fix(context)
+ return ans
+
+ def __rdiv__(self, other, context=None):
+ """Swaps self/other and returns __div__."""
+ other = _convert_other(other)
+ if other is NotImplemented:
+ return other
+ return other.__div__(self, context=context)
+ __rtruediv__ = __rdiv__
+
+ def __divmod__(self, other, context=None):
+ """
+ (self // other, self % other)
+ """
+ return self._divide(other, 1, context)
+
+ 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 self._is_special or other._is_special:
+ ans = self._check_nans(other, context)
+ if ans:
+ return ans
+
+ if self and not other:
+ return context._raise_error(InvalidOperation, 'x % 0')
+
+ return self._divide(other, 3, context)[1]
+
+ 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
+ """
+ other = _convert_other(other)
+ if other is NotImplemented:
+ return other
+
+ if self._is_special or other._is_special:
+ ans = self._check_nans(other, context)
+ if ans:
+ return ans
+ if self and not other:
+ return context._raise_error(InvalidOperation, 'x % 0')
+
+ if context is None:
+ context = getcontext()
+ # If DivisionImpossible causes an error, do not leave Rounded/Inexact
+ # ignored in the calling function.
+ context = context._shallow_copy()
+ flags = context._ignore_flags(Rounded, Inexact)
+ #keep DivisionImpossible flags
+ (side, r) = self.__divmod__(other, context=context)
+
+ if r._isnan():
+ context._regard_flags(*flags)
+ return r
+
+ context = context._shallow_copy()
+ rounding = context._set_rounding_decision(NEVER_ROUND)
+
+ if other._sign:
+ comparison = other.__div__(Decimal(-2), context=context)
+ else:
+ comparison = other.__div__(Decimal(2), context=context)
+
+ context._set_rounding_decision(rounding)
+ context._regard_flags(*flags)
+
+ s1, s2 = r._sign, comparison._sign
+ r._sign, comparison._sign = 0, 0
+
+ if r < comparison:
+ r._sign, comparison._sign = s1, s2
+ #Get flags now
+ self.__divmod__(other, context=context)
+ return r._fix(context)
+ r._sign, comparison._sign = s1, s2
+
+ rounding = context._set_rounding_decision(NEVER_ROUND)
+
+ (side, r) = self.__divmod__(other, context=context)
+ context._set_rounding_decision(rounding)
+ if r._isnan():
+ return r
+
+ decrease = not side._iseven()
+ rounding = context._set_rounding_decision(NEVER_ROUND)
+ side = side.__abs__(context=context)
+ context._set_rounding_decision(rounding)
+
+ s1, s2 = r._sign, comparison._sign
+ r._sign, comparison._sign = 0, 0
+ if r > comparison or decrease and r == comparison:
+ r._sign, comparison._sign = s1, s2
+ context.prec += 1
+ if len(side.__add__(Decimal(1), context=context)._int) >= context.prec:
+ context.prec -= 1
+ return context._raise_error(DivisionImpossible)[1]
+ context.prec -= 1
+ if self._sign == other._sign:
+ r = r.__sub__(other, context=context)
+ else:
+ r = r.__add__(other, context=context)
+ else:
+ r._sign, comparison._sign = s1, s2
+
+ return r._fix(context)
+
+ def __floordiv__(self, other, context=None):
+ """self // other"""
+ return self._divide(other, 2, 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."""
+ return float(str(self))
+
+ def __int__(self):
+ """Converts self to an int, truncating if necessary."""
+ if self._is_special:
+ if self._isnan():
+ context = getcontext()
+ return context._raise_error(InvalidContext)
+ elif self._isinfinity():
+ raise OverflowError, "Cannot convert infinity to long"
+ if self._exp >= 0:
+ s = ''.join(map(str, self._int)) + '0'*self._exp
+ else:
+ s = ''.join(map(str, self._int))[:self._exp]
+ if s == '':
+ s = '0'
+ sign = '-'*self._sign
+ return int(sign + s)
+
+ def __long__(self):
+ """Converts to a long.
+
+ Equivalent to long(int(self))
+ """
+ return long(self.__int__())
+
+ 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:
+ return self
+ if context is None:
+ context = getcontext()
+ prec = context.prec
+ ans = self._fixexponents(context)
+ if len(ans._int) > prec:
+ ans = ans._round(prec, context=context)
+ ans = ans._fixexponents(context)
+ return ans
+
+ def _fixexponents(self, context):
+ """Fix the exponents and return a copy with the exponent in bounds.
+ Only call if known to not be a special value.
+ """
+ folddown = context._clamp
+ Emin = context.Emin
+ ans = self
+ ans_adjusted = ans.adjusted()
+ if ans_adjusted < Emin:
+ Etiny = context.Etiny()
+ if ans._exp < Etiny:
+ if not ans:
+ ans = Decimal(self)
+ ans._exp = Etiny
+ context._raise_error(Clamped)
+ return ans
+ ans = ans._rescale(Etiny, context=context)
+ #It isn't zero, and exp < Emin => subnormal
+ context._raise_error(Subnormal)
+ if context.flags[Inexact]:
+ context._raise_error(Underflow)
+ else:
+ if ans:
+ #Only raise subnormal if non-zero.
+ context._raise_error(Subnormal)
+ else:
+ Etop = context.Etop()
+ if folddown and ans._exp > Etop:
+ context._raise_error(Clamped)
+ ans = ans._rescale(Etop, context=context)
+ else:
+ Emax = context.Emax
+ if ans_adjusted > Emax:
+ if not ans:
+ ans = Decimal(self)
+ ans._exp = Emax
+ context._raise_error(Clamped)
+ return ans
+ context._raise_error(Inexact)
+ context._raise_error(Rounded)
+ return context._raise_error(Overflow, 'above Emax', ans._sign)
+ return ans
+
+ def _round(self, prec=None, rounding=None, context=None):
+ """Returns a rounded version of self.
+
+ You can specify the precision or rounding method. Otherwise, the
+ context determines it.
+ """
+
+ if self._is_special:
+ ans = self._check_nans(context=context)
+ if ans:
+ return ans
+
+ if self._isinfinity():
+ return Decimal(self)
+
+ if context is None:
+ context = getcontext()
+
+ if rounding is None:
+ rounding = context.rounding
+ if prec is None:
+ prec = context.prec
+
+ if not self:
+ if prec <= 0:
+ dig = (0,)
+ exp = len(self._int) - prec + self._exp
+ else:
+ dig = (0,) * prec
+ exp = len(self._int) + self._exp - prec
+ ans = Decimal((self._sign, dig, exp))
+ context._raise_error(Rounded)
+ return ans
+
+ if prec == 0:
+ temp = Decimal(self)
+ temp._int = (0,)+temp._int
+ prec = 1
+ elif prec < 0:
+ exp = self._exp + len(self._int) - prec - 1
+ temp = Decimal( (self._sign, (0, 1), exp))
+ prec = 1
+ else:
+ temp = Decimal(self)
+
+ numdigits = len(temp._int)
+ if prec == numdigits:
+ return temp
+
+ # See if we need to extend precision
+ expdiff = prec - numdigits
+ if expdiff > 0:
+ tmp = list(temp._int)
+ tmp.extend([0] * expdiff)
+ ans = Decimal( (temp._sign, tmp, temp._exp - expdiff))
+ return ans
+
+ #OK, but maybe all the lost digits are 0.
+ lostdigits = self._int[expdiff:]
+ if lostdigits == (0,) * len(lostdigits):
+ ans = Decimal( (temp._sign, temp._int[:prec], temp._exp - expdiff))
+ #Rounded, but not Inexact
+ context._raise_error(Rounded)
+ return ans
+
+ # Okay, let's round and lose data
+
+ this_function = getattr(temp, self._pick_rounding_function[rounding])
+ #Now we've got the rounding function
+
+ if prec != context.prec:
+ context = context._shallow_copy()
+ context.prec = prec
+ ans = this_function(prec, expdiff, context)
+ context._raise_error(Rounded)
+ context._raise_error(Inexact, 'Changed in rounding')
+
+ return ans
+
+ _pick_rounding_function = {}
+
+ def _round_down(self, prec, expdiff, context):
+ """Also known as round-towards-0, truncate."""
+ return Decimal( (self._sign, self._int[:prec], self._exp - expdiff) )
+
+ def _round_half_up(self, prec, expdiff, context, tmp = None):
+ """Rounds 5 up (away from 0)"""
+
+ if tmp is None:
+ tmp = Decimal( (self._sign,self._int[:prec], self._exp - expdiff))
+ if self._int[prec] >= 5:
+ tmp = tmp._increment(round=0, context=context)
+ if len(tmp._int) > prec:
+ return Decimal( (tmp._sign, tmp._int[:-1], tmp._exp + 1))
+ return tmp
+
+ def _round_half_even(self, prec, expdiff, context):
+ """Round 5 to even, rest to nearest."""
+
+ tmp = Decimal( (self._sign, self._int[:prec], self._exp - expdiff))
+ half = (self._int[prec] == 5)
+ if half:
+ for digit in self._int[prec+1:]:
+ if digit != 0:
+ half = 0
+ break
+ if half:
+ if self._int[prec-1] & 1 == 0:
+ return tmp
+ return self._round_half_up(prec, expdiff, context, tmp)
+
+ def _round_half_down(self, prec, expdiff, context):
+ """Round 5 down"""
+
+ tmp = Decimal( (self._sign, self._int[:prec], self._exp - expdiff))
+ half = (self._int[prec] == 5)
+ if half:
+ for digit in self._int[prec+1:]:
+ if digit != 0:
+ half = 0
+ break
+ if half:
+ return tmp
+ return self._round_half_up(prec, expdiff, context, tmp)
+
+ def _round_up(self, prec, expdiff, context):
+ """Rounds away from 0."""
+ tmp = Decimal( (self._sign, self._int[:prec], self._exp - expdiff) )
+ for digit in self._int[prec:]:
+ if digit != 0:
+ tmp = tmp._increment(round=1, context=context)
+ if len(tmp._int) > prec:
+ return Decimal( (tmp._sign, tmp._int[:-1], tmp._exp + 1))
+ else:
+ return tmp
+ return tmp
+
+ def _round_ceiling(self, prec, expdiff, context):
+ """Rounds up (not away from 0 if negative.)"""
+ if self._sign:
+ return self._round_down(prec, expdiff, context)
+ else:
+ return self._round_up(prec, expdiff, context)
+
+ def _round_floor(self, prec, expdiff, context):
+ """Rounds down (not towards 0 if negative)"""
+ if not self._sign:
+ return self._round_down(prec, expdiff, context)
+ else:
+ return self._round_up(prec, expdiff, context)
+
+ def __pow__(self, n, modulo = None, context=None):
+ """Return self ** n (mod modulo)
+
+ If modulo is None (default), don't take it mod modulo.
+ """
+ n = _convert_other(n)
+ if n is NotImplemented:
+ return n
+
+ if context is None:
+ context = getcontext()
+
+ if self._is_special or n._is_special or n.adjusted() > 8:
+ #Because the spot << doesn't work with really big exponents
+ if n._isinfinity() or n.adjusted() > 8:
+ return context._raise_error(InvalidOperation, 'x ** INF')
+
+ ans = self._check_nans(n, context)
+ if ans:
+ return ans
+
+ if not n._isinteger():
+ return context._raise_error(InvalidOperation, 'x ** (non-integer)')
+
+ if not self and not n:
+ return context._raise_error(InvalidOperation, '0 ** 0')
+
+ if not n:
+ return Decimal(1)
+
+ if self == Decimal(1):
+ return Decimal(1)
+
+ sign = self._sign and not n._iseven()
+ n = int(n)
+
+ if self._isinfinity():
+ if modulo:
+ return context._raise_error(InvalidOperation, 'INF % x')
+ if n > 0:
+ return Infsign[sign]
+ return Decimal( (sign, (0,), 0) )
+
+ #with ludicrously large exponent, just raise an overflow and return inf.
+ if not modulo and n > 0 and (self._exp + len(self._int) - 1) * n > context.Emax \
+ and self:
+
+ tmp = Decimal('inf')
+ tmp._sign = sign
+ context._raise_error(Rounded)
+ context._raise_error(Inexact)
+ context._raise_error(Overflow, 'Big power', sign)
+ return tmp
+
+ elength = len(str(abs(n)))
+ firstprec = context.prec
+
+ if not modulo and firstprec + elength + 1 > DefaultContext.Emax:
+ return context._raise_error(Overflow, 'Too much precision.', sign)
+
+ mul = Decimal(self)
+ val = Decimal(1)
+ context = context._shallow_copy()
+ context.prec = firstprec + elength + 1
+ if n < 0:
+ #n is a long now, not Decimal instance
+ n = -n
+ mul = Decimal(1).__div__(mul, context=context)
+
+ spot = 1
+ while spot <= n:
+ spot <<= 1
+
+ spot >>= 1
+ #Spot is the highest power of 2 less than n
+ while spot:
+ val = val.__mul__(val, context=context)
+ if val._isinfinity():
+ val = Infsign[sign]
+ break
+ if spot & n:
+ val = val.__mul__(mul, context=context)
+ if modulo is not None:
+ val = val.__mod__(modulo, context=context)
+ spot >>= 1
+ context.prec = firstprec
+
+ if context._rounding_decision == ALWAYS_ROUND:
+ return val._fix(context)
+ return val
+
+ 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 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 Decimal( (dup._sign, (0,), 0) )
+ end = len(dup._int)
+ exp = dup._exp
+ while dup._int[end-1] == 0:
+ exp += 1
+ end -= 1
+ return Decimal( (dup._sign, dup._int[:end], exp) )
+
+
+ def quantize(self, exp, rounding=None, context=None, watchexp=1):
+ """Quantize self so its exponent is the same as that of exp.
+
+ Similar to self._rescale(exp._exp) but with error checking.
+ """
+ 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 self #if both are inf, it is OK
+ if context is None:
+ context = getcontext()
+ return context._raise_error(InvalidOperation,
+ 'quantize with one INF')
+ return self._rescale(exp._exp, rounding, context, watchexp)
+
+ def same_quantum(self, other):
+ """Test whether self and other have the same exponent.
+
+ same as self._exp == other._exp, except NaN == sNaN
+ """
+ if self._is_special or other._is_special:
+ if self._isnan() or other._isnan():
+ return self._isnan() and other._isnan() and True
+ if self._isinfinity() or other._isinfinity():
+ return self._isinfinity() and other._isinfinity() and True
+ return self._exp == other._exp
+
+ def _rescale(self, exp, rounding=None, context=None, watchexp=1):
+ """Rescales so that the exponent is exp.
+
+ exp = exp to scale to (an integer)
+ rounding = rounding version
+ watchexp: if set (default) an error is returned if exp is greater
+ than Emax or less than Etiny.
+ """
+ if context is None:
+ context = getcontext()
+
+ if self._is_special:
+ if self._isinfinity():
+ return context._raise_error(InvalidOperation, 'rescale with an INF')
+
+ ans = self._check_nans(context=context)
+ if ans:
+ return ans
+
+ if watchexp and (context.Emax < exp or context.Etiny() > exp):
+ return context._raise_error(InvalidOperation, 'rescale(a, INF)')
+
+ if not self:
+ ans = Decimal(self)
+ ans._int = (0,)
+ ans._exp = exp
+ return ans
+
+ diff = self._exp - exp
+ digits = len(self._int) + diff
+
+ if watchexp and digits > context.prec:
+ return context._raise_error(InvalidOperation, 'Rescale > prec')
+
+ tmp = Decimal(self)
+ tmp._int = (0,) + tmp._int
+ digits += 1
+
+ if digits < 0:
+ tmp._exp = -digits + tmp._exp
+ tmp._int = (0,1)
+ digits = 1
+ tmp = tmp._round(digits, rounding, context=context)
+
+ if tmp._int[0] == 0 and len(tmp._int) > 1:
+ tmp._int = tmp._int[1:]
+ tmp._exp = exp
+
+ tmp_adjusted = tmp.adjusted()
+ if tmp and tmp_adjusted < context.Emin:
+ context._raise_error(Subnormal)
+ elif tmp and tmp_adjusted > context.Emax:
+ return context._raise_error(InvalidOperation, 'rescale(a, INF)')
+ return tmp
+
+ def to_integral(self, rounding=None, context=None):
+ """Rounds to the nearest integer, without raising inexact, rounded."""
+ if self._is_special:
+ ans = self._check_nans(context=context)
+ if ans:
+ return ans
+ if self._exp >= 0:
+ return self
+ if context is None:
+ context = getcontext()
+ flags = context._ignore_flags(Rounded, Inexact)
+ ans = self._rescale(0, rounding, context=context)
+ context._regard_flags(flags)
+ return ans
+
+ def sqrt(self, context=None):
+ """Return the square root of self.
+
+ Uses a converging algorithm (Xn+1 = 0.5*(Xn + self / Xn))
+ Should quadratically approach the right answer.
+ """
+ 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, using round_down.
+ #if self._exp < 0:
+ # exp = (self._exp+1) // 2
+ #else:
+ exp = (self._exp) // 2
+ if self._sign == 1:
+ #sqrt(-0) = -0
+ return Decimal( (1, (0,), exp))
+ else:
+ return Decimal( (0, (0,), exp))
+
+ if context is None:
+ context = getcontext()
+
+ if self._sign == 1:
+ return context._raise_error(InvalidOperation, 'sqrt(-x), x > 0')
+
+ tmp = Decimal(self)
+
+ expadd = tmp._exp // 2
+ if tmp._exp & 1:
+ tmp._int += (0,)
+ tmp._exp = 0
+ else:
+ tmp._exp = 0
+
+ context = context._shallow_copy()
+ flags = context._ignore_all_flags()
+ firstprec = context.prec
+ context.prec = 3
+ if tmp.adjusted() & 1 == 0:
+ ans = Decimal( (0, (8,1,9), tmp.adjusted() - 2) )
+ ans = ans.__add__(tmp.__mul__(Decimal((0, (2,5,9), -2)),
+ context=context), context=context)
+ ans._exp -= 1 + tmp.adjusted() // 2
+ else:
+ ans = Decimal( (0, (2,5,9), tmp._exp + len(tmp._int)- 3) )
+ ans = ans.__add__(tmp.__mul__(Decimal((0, (8,1,9), -3)),
+ context=context), context=context)
+ ans._exp -= 1 + tmp.adjusted() // 2
+
+ #ans is now a linear approximation.
+
+ Emax, Emin = context.Emax, context.Emin
+ context.Emax, context.Emin = DefaultContext.Emax, DefaultContext.Emin
+
+ half = Decimal('0.5')
+
+ maxp = firstprec + 2
+ rounding = context._set_rounding(ROUND_HALF_EVEN)
+ while 1:
+ context.prec = min(2*context.prec - 2, maxp)
+ ans = half.__mul__(ans.__add__(tmp.__div__(ans, context=context),
+ context=context), context=context)
+ if context.prec == maxp:
+ break
+
+ #round to the answer's precision-- the only error can be 1 ulp.
+ context.prec = firstprec
+ prevexp = ans.adjusted()
+ ans = ans._round(context=context)
+
+ #Now, check if the other last digits are better.
+ context.prec = firstprec + 1
+ # In case we rounded up another digit and we should actually go lower.
+ if prevexp != ans.adjusted():
+ ans._int += (0,)
+ ans._exp -= 1
+
+
+ lower = ans.__sub__(Decimal((0, (5,), ans._exp-1)), context=context)
+ context._set_rounding(ROUND_UP)
+ if lower.__mul__(lower, context=context) > (tmp):
+ ans = ans.__sub__(Decimal((0, (1,), ans._exp)), context=context)
+
+ else:
+ upper = ans.__add__(Decimal((0, (5,), ans._exp-1)),context=context)
+ context._set_rounding(ROUND_DOWN)
+ if upper.__mul__(upper, context=context) < tmp:
+ ans = ans.__add__(Decimal((0, (1,), ans._exp)),context=context)
+
+ ans._exp += expadd
+
+ context.prec = firstprec
+ context.rounding = rounding
+ ans = ans._fix(context)
+
+ rounding = context._set_rounding_decision(NEVER_ROUND)
+ if not ans.__mul__(ans, context=context) == self:
+ # Only rounded/inexact if here.
+ context._regard_flags(flags)
+ context._raise_error(Rounded)
+ context._raise_error(Inexact)
+ else:
+ #Exact answer, so let's set the exponent right.
+ #if self._exp < 0:
+ # exp = (self._exp +1)// 2
+ #else:
+ exp = self._exp // 2
+ context.prec += ans._exp - exp
+ ans = ans._rescale(exp, context=context)
+ context.prec = firstprec
+ context._regard_flags(flags)
+ context.Emax, context.Emin = Emax, Emin
+
+ return ans._fix(context)
+
+ 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)
+ if other is NotImplemented:
+ return other
+
+ 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 != 2:
+ return self
+ if sn == 1 and on != 2:
+ return other
+ return self._check_nans(other, context)
+
+ ans = self
+ 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.
+ if self._sign != other._sign:
+ if self._sign:
+ ans = other
+ elif self._exp < other._exp and not self._sign:
+ ans = other
+ elif self._exp > other._exp and self._sign:
+ ans = other
+ elif c == -1:
+ ans = other
+
+ if context is None:
+ context = getcontext()
+ if context._rounding_decision == ALWAYS_ROUND:
+ return ans._fix(context)
+ return ans
+
+ 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)
+ if other is NotImplemented:
+ return other
+
+ 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 != 2:
+ return self
+ if sn == 1 and on != 2:
+ return other
+ return self._check_nans(other, context)
+
+ ans = self
+ 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.
+ if self._sign != other._sign:
+ if other._sign:
+ ans = other
+ elif self._exp > other._exp and not self._sign:
+ ans = other
+ elif self._exp < other._exp and self._sign:
+ ans = other
+ elif c == 1:
+ ans = other
+
+ if context is None:
+ context = getcontext()
+ if context._rounding_decision == ALWAYS_ROUND:
+ return ans._fix(context)
+ return ans
+
+ def _isinteger(self):
+ """Returns whether self is an integer"""
+ if self._exp >= 0:
+ return True
+ rest = self._int[self._exp:]
+ return rest == (0,)*len(rest)
+
+ def _iseven(self):
+ """Returns 1 if self is even. Assumes self is an integer."""
+ if self._exp > 0:
+ return 1
+ return self._int[-1+self._exp] & 1 == 0
+
+ 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
+
+ # support for pickling, copy, and deepcopy
+ def __reduce__(self):
+ return (self.__class__, (str(self),))
+
+ def __copy__(self):
+ if type(self) == Decimal:
+ return self # I'm immutable; therefore I am my own clone
+ return self.__class__(str(self))
+
+ def __deepcopy__(self, memo):
+ if type(self) == Decimal:
+ return self # My components are also immutable
+ return self.__class__(str(self))
+
+##### 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)
+ _rounding_decision - ALWAYS_ROUND, NEVER_ROUND -- do 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 incremented.
+ (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,
+ _rounding_decision=None,
+ Emin=None, Emax=None,
+ capitals=None, _clamp=0,
+ _ignored_flags=None):
+ if flags is None:
+ flags = []
+ if _ignored_flags is None:
+ _ignored_flags = []
+ if not isinstance(flags, dict):
+ flags = dict([(s,s in flags) for s in _signals])
+ del s
+ if traps is not None and not isinstance(traps, dict):
+ traps = dict([(s,s in traps) for s in _signals])
+ del s
+ for name, val in locals().items():
+ if val is None:
+ setattr(self, name, _copy.copy(getattr(DefaultContext, name)))
+ else:
+ setattr(self, name, val)
+ del self.self
+
+ 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))
+ s.append('flags=[' + ', '.join([f.__name__ for f, v in self.flags.items() if v]) + ']')
+ s.append('traps=[' + ', '.join([t.__name__ for t, v in self.traps.items() if v]) + ']')
+ 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._rounding_decision, 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._rounding_decision, 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 increments the flag, then, if the corresponding
+ trap_enabler is set, it reaises the exception. Otherwise, it returns
+ the default value after incrementing 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)
+
+ def __hash__(self):
+ """A Context cannot be hashed."""
+ # We inherit object.__hash__, so we must deny this explicitly
+ raise TypeError, "Cannot hash a Context."
+
+ 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_decision(self, type):
+ """Sets the rounding decision.
+
+ Sets the rounding decision, and returns the current (previous)
+ rounding decision. Often used like:
+
+ context = context._shallow_copy()
+ # That so you don't change the calling context
+ # if an error occurs in the middle (say DivisionImpossible is raised).
+
+ rounding = context._set_rounding_decision(NEVER_ROUND)
+ instance = instance / Decimal(2)
+ context._set_rounding_decision(rounding)
+
+ This will make it not round for that operation.
+ """
+
+ rounding = self._rounding_decision
+ self._rounding_decision = type
+ return rounding
+
+ 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."""
+ d = Decimal(num, context=self)
+ return d._fix(self)
+
+ #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")
+ """
+ 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")
+ """
+ return a.__add__(b, context=self)
+
+ def _apply(self, a):
+ return str(a._fix(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")
+ """
+ return a.compare(b, context=self)
+
+ 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")
+ """
+ return a.__div__(b, context=self)
+
+ 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")
+ """
+ return a.__floordiv__(b, context=self)
+
+ def divmod(self, a, b):
+ return a.__divmod__(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 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")
+ """
+ return a.max(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 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")
+ """
+ return a.min(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")
+ """
+ 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")
+ """
+ return a.__mul__(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")
+ """
+ return a.normalize(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")
+ """
+ return a.__pos__(context=self)
+
+ def power(self, a, b, modulo=None):
+ """Raises a to the power of b, to modulo if given.
+
+ The right-hand operand must be a whole number whose integer part (after
+ any exponent has been applied) has no more than 9 digits and whose
+ fractional part (if any) is all zeros before any rounding. The operand
+ may be positive, negative, or zero; if negative, the absolute value of
+ the power is used, and the left-hand operand is inverted (divided into
+ 1) before use.
+
+ If the increased precision needed for the intermediate calculations
+ exceeds the capabilities of the implementation then an Invalid operation
+ condition is raised.
+
+ If, when raising to a negative power, an underflow occurs during the
+ division into 1, the operation is not halted at that point but
+ continues.
+
+ >>> ExtendedContext.power(Decimal('2'), Decimal('3'))
+ Decimal("8")
+ >>> ExtendedContext.power(Decimal('2'), Decimal('-3'))
+ Decimal("0.125")
+ >>> ExtendedContext.power(Decimal('1.7'), Decimal('8'))
+ Decimal("69.7575744")
+ >>> ExtendedContext.power(Decimal('Infinity'), Decimal('-2'))
+ Decimal("0")
+ >>> ExtendedContext.power(Decimal('Infinity'), Decimal('-1'))
+ Decimal("0")
+ >>> ExtendedContext.power(Decimal('Infinity'), Decimal('0'))
+ Decimal("1")
+ >>> ExtendedContext.power(Decimal('Infinity'), Decimal('1'))
+ Decimal("Infinity")
+ >>> ExtendedContext.power(Decimal('Infinity'), Decimal('2'))
+ Decimal("Infinity")
+ >>> ExtendedContext.power(Decimal('-Infinity'), Decimal('-2'))
+ Decimal("0")
+ >>> ExtendedContext.power(Decimal('-Infinity'), Decimal('-1'))
+ Decimal("-0")
+ >>> ExtendedContext.power(Decimal('-Infinity'), Decimal('0'))
+ Decimal("1")
+ >>> ExtendedContext.power(Decimal('-Infinity'), Decimal('1'))
+ Decimal("-Infinity")
+ >>> ExtendedContext.power(Decimal('-Infinity'), Decimal('2'))
+ Decimal("Infinity")
+ >>> ExtendedContext.power(Decimal('0'), Decimal('0'))
+ Decimal("NaN")
+ """
+ return a.__pow__(b, modulo, context=self)
+
+ def quantize(self, a, b):
+ """Returns a value equal to 'a' (rounded) and 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")
+ """
+ return a.quantize(b, context=self)
+
+ 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")
+ """
+ return a.__mod__(b, context=self)
+
+ 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")
+ """
+ return a.remainder_near(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
+ """
+ return a.same_quantum(b)
+
+ def sqrt(self, a):
+ """Returns the 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.prec
+ 9
+ """
+ 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")
+ """
+ return a.__sub__(b, context=self)
+
+ def to_eng_string(self, a):
+ """Converts a number to a string, using scientific notation.
+
+ The operation is not affected by the context.
+ """
+ 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.
+ """
+ return a.__str__(context=self)
+
+ def to_integral(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(Decimal('2.1'))
+ Decimal("2")
+ >>> ExtendedContext.to_integral(Decimal('100'))
+ Decimal("100")
+ >>> ExtendedContext.to_integral(Decimal('100.0'))
+ Decimal("100")
+ >>> ExtendedContext.to_integral(Decimal('101.5'))
+ Decimal("102")
+ >>> ExtendedContext.to_integral(Decimal('-101.5'))
+ Decimal("-102")
+ >>> ExtendedContext.to_integral(Decimal('10E+5'))
+ Decimal("1.0E+6")
+ >>> ExtendedContext.to_integral(Decimal('7.89E+77'))
+ Decimal("7.89E+77")
+ >>> ExtendedContext.to_integral(Decimal('-Inf'))
+ Decimal("-Infinity")
+ """
+ return a.to_integral(context=self)
+
+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
+ cum = 0
+ for digit in value._int:
+ cum = cum * 10 + digit
+ self.int = cum
+ 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, shouldround = 0, prec = 0):
+ """Normalizes op1, op2 to have the same exp and length of coefficient.
+
+ Done during addition.
+ """
+ # Yes, the exponent is a long, but the difference between exponents
+ # must be an int-- otherwise you'd get a big memory problem.
+ numdigits = int(op1.exp - op2.exp)
+ if numdigits < 0:
+ numdigits = -numdigits
+ tmp = op2
+ other = op1
+ else:
+ tmp = op1
+ other = op2
+
+
+ if shouldround and numdigits > prec + 1:
+ # Big difference in exponents - check the adjusted exponents
+ tmp_len = len(str(tmp.int))
+ other_len = len(str(other.int))
+ if numdigits > (other_len + prec + 1 - tmp_len):
+ # If the difference in adjusted exps is > prec+1, we know
+ # other is insignificant, so might as well put a 1 after the precision.
+ # (since this is only for addition.) Also stops use of massive longs.
+
+ extend = prec + 2 - tmp_len
+ if extend <= 0:
+ extend = 1
+ tmp.int *= 10 ** extend
+ tmp.exp -= extend
+ other.int = 1
+ other.exp = tmp.exp
+ return op1, op2
+
+ tmp.int *= 10 ** numdigits
+ tmp.exp -= numdigits
+ return op1, op2
+
+def _adjust_coefficients(op1, op2):
+ """Adjust op1, op2 so that op2.int * 10 > op1.int >= op2.int.
+
+ Returns the adjusted op1, op2 as well as the change in op1.exp-op2.exp.
+
+ Used on _WorkRep instances during division.
+ """
+ adjust = 0
+ #If op1 is smaller, make it larger
+ while op2.int > op1.int:
+ op1.int *= 10
+ op1.exp -= 1
+ adjust += 1
+
+ #If op2 is too small, make it larger
+ while op1.int >= (10 * op2.int):
+ op2.int *= 10
+ op2.exp -= 1
+ adjust -= 1
+
+ return op1, op2, adjust
+
+##### Helper Functions ########################################
+
+def _convert_other(other):
+ """Convert other to Decimal.
+
+ Verifies that it's ok to use in an implicit construction.
+ """
+ if isinstance(other, Decimal):
+ return other
+ if isinstance(other, (int, long)):
+ return Decimal(other)
+ return NotImplemented
+
+_infinity_map = {
+ 'inf' : 1,
+ 'infinity' : 1,
+ '+inf' : 1,
+ '+infinity' : 1,
+ '-inf' : -1,
+ '-infinity' : -1
+}
+
+def _isinfinity(num):
+ """Determines whether a string or float is infinity.
+
+ +1 for negative infinity; 0 for finite ; +1 for positive infinity
+ """
+ num = str(num).lower()
+ return _infinity_map.get(num, 0)
+
+def _isnan(num):
+ """Determines whether a string or float is NaN
+
+ (1, sign, diagnostic info as string) => NaN
+ (2, sign, diagnostic info as string) => sNaN
+ 0 => not a NaN
+ """
+ num = str(num).lower()
+ if not num:
+ return 0
+
+ #get the sign, get rid of trailing [+-]
+ sign = 0
+ if num[0] == '+':
+ num = num[1:]
+ elif num[0] == '-': #elif avoids '+-nan'
+ num = num[1:]
+ sign = 1
+
+ if num.startswith('nan'):
+ if len(num) > 3 and not num[3:].isdigit(): #diagnostic info
+ return 0
+ return (1, sign, num[3:].lstrip('0'))
+ if num.startswith('snan'):
+ if len(num) > 4 and not num[4:].isdigit():
+ return 0
+ return (2, sign, num[4:].lstrip('0'))
+ return 0
+
+
+##### 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=[],
+ _rounding_decision=ALWAYS_ROUND,
+ 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=[],
+)
+
+
+##### Useful Constants (internal use only) ####################
+
+#Reusable defaults
+Inf = Decimal('Inf')
+negInf = Decimal('-Inf')
+
+#Infsign[sign] is infinity w/ that sign
+Infsign = (Inf, negInf)
+
+NaN = Decimal('NaN')
+
+
+##### crud for parsing strings #################################
+import re
+
+# There's an optional sign at the start, and an optional exponent
+# at the end. The exponent has an optional sign and at least one
+# digit. In between, must have either at least one digit followed
+# by an optional fraction, or a decimal point followed by at least
+# one digit. Yuck.
+
+_parser = re.compile(r"""
+# \s*
+ (?P<sign>[-+])?
+ (
+ (?P<int>\d+) (\. (?P<frac>\d*))?
+ |
+ \. (?P<onlyfrac>\d+)
+ )
+ ([eE](?P<exp>[-+]? \d+))?
+# \s*
+ $
+""", re.VERBOSE).match #Uncomment the \s* to allow leading or trailing spaces.
+
+del re
+
+# return sign, n, p s.t. float string value == -1**sign * n * 10**p exactly
+
+def _string2exact(s):
+ m = _parser(s)
+ if m is None:
+ raise ValueError("invalid literal for Decimal: %r" % s)
+
+ if m.group('sign') == "-":
+ sign = 1
+ else:
+ sign = 0
+
+ exp = m.group('exp')
+ if exp is None:
+ exp = 0
+ else:
+ exp = int(exp)
+
+ intpart = m.group('int')
+ if intpart is None:
+ intpart = ""
+ fracpart = m.group('onlyfrac')
+ else:
+ fracpart = m.group('frac')
+ if fracpart is None:
+ fracpart = ""
+
+ exp -= len(fracpart)
+
+ mantissa = intpart + fracpart
+ tmp = map(int, mantissa)
+ backup = tmp
+ while tmp and tmp[0] == 0:
+ del tmp[0]
+
+ # It's a zero
+ if not tmp:
+ if backup:
+ return (sign, tuple(backup), exp)
+ return (sign, (0,), exp)
+ mantissa = tuple(tmp)
+
+ return (sign, mantissa, exp)
+
+
+if __name__ == '__main__':
+ import doctest, sys
+ doctest.testmod(sys.modules[__name__])
--- /dev/null
+++ b/sys/lib/python/difflib.py
@@ -1,0 +1,2019 @@
+#! /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']
+
+import heapq
+
+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=''):
+ """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().
+ """
+
+ # 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 has_key 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% of
+ # its elements. DOES NOT WORK for x in a!
+
+ self.isjunk = isjunk
+ self.a = self.b = None
+ 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% 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
+ n = len(b)
+ self.b2j = b2j = {}
+ populardict = {}
+ for i, elt in enumerate(b):
+ if elt in b2j:
+ indices = b2j[elt]
+ if n >= 200 and len(indices) * 100 > n:
+ populardict[elt] = 1
+ del indices[:]
+ else:
+ indices.append(i)
+ else:
+ b2j[elt] = [i]
+
+ # Purge leftover indices for popular elements.
+ for elt in populardict:
+ del b2j[elt]
+
+ # Now b2j.keys() contains elements uniquely, and especially when
+ # the sequence is a string, that's usually a good deal smaller
+ # than len(string). The difference is the number of isjunk calls
+ # saved.
+ isjunk = self.isjunk
+ junkdict = {}
+ if isjunk:
+ for d in populardict, b2j:
+ for elt in d.keys():
+ if isjunk(elt):
+ junkdict[elt] = 1
+ del d[elt]
+
+ # Now for x in b, isjunk(x) == x in junkdict, but the
+ # latter is much faster. Note too that while there may be a
+ # lot of junk in the sequence, the number of *unique* junk
+ # elements is probably small. So the memory burden of keeping
+ # this dict alive is likely trivial compared to the size of b2j.
+ self.isbjunk = junkdict.has_key
+ self.isbpopular = populardict.has_key
+
+ 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)
+ (0, 4, 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)
+ (1, 0, 4)
+
+ If no blocks match, return (alo, blo, 0).
+
+ >>> s = SequenceMatcher(None, "ab", "c")
+ >>> s.find_longest_match(0, 2, 0, 1)
+ (0, 0, 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 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()
+ [(0, 0, 2), (3, 2, 2), (5, 4, 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 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.has_key, 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', '\t\tabcdefGhijkl\n',
+ ... ' ^ ^ ^ ', '+ ^ ^ ^ ')
+ >>> for line in results: print repr(line)
+ ...
+ '- \tabcDefghiJkl\n'
+ '? \t ^ ^ ^\n'
+ '+ \t\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], " "))
+ 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
+
+
+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 format returned by time.ctime().
+
+ Example:
+
+ >>> for line in unified_diff('one two three four'.split(),
+ ... 'zero one tree four'.split(), 'Original', 'Current',
+ ... 'Sat Jan 26 23:30:50 1991', 'Fri Jun 06 10:20:52 2003',
+ ... lineterm=''):
+ ... print line
+ --- Original Sat Jan 26 23:30:50 1991
+ +++ Current Fri Jun 06 10:20:52 2003
+ @@ -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:
+ yield '--- %s %s%s' % (fromfile, fromfiledate, lineterm)
+ yield '+++ %s %s%s' % (tofile, tofiledate, lineterm)
+ started = True
+ i1, i2, j1, j2 = group[0][1], group[-1][2], group[0][3], group[-1][4]
+ yield "@@ -%d,%d +%d,%d @@%s" % (i1+1, i2-i1, j1+1, j2-j1, lineterm)
+ for tag, i1, i2, j1, j2 in group:
+ if tag == 'equal':
+ for line in a[i1:i2]:
+ yield ' ' + line
+ continue
+ if tag == 'replace' or tag == 'delete':
+ for line in a[i1:i2]:
+ yield '-' + line
+ if tag == 'replace' or tag == 'insert':
+ for line in b[j1:j2]:
+ yield '+' + line
+
+# 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 format returned
+ by time.ctime(). 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',
+ ... 'Sat Jan 26 23:30:50 1991', 'Fri Jun 06 10:22:46 2003')),
+ *** Original Sat Jan 26 23:30:50 1991
+ --- Current Fri Jun 06 10:22:46 2003
+ ***************
+ *** 1,4 ****
+ one
+ ! two
+ ! three
+ four
+ --- 1,4 ----
+ + zero
+ one
+ ! tree
+ four
+ """
+
+ started = False
+ prefixmap = {'insert':'+ ', 'delete':'- ', 'replace':'! ', 'equal':' '}
+ for group in SequenceMatcher(None,a,b).get_grouped_opcodes(n):
+ if not started:
+ yield '*** %s %s%s' % (fromfile, fromfiledate, lineterm)
+ yield '--- %s %s%s' % (tofile, tofiledate, lineterm)
+ started = True
+
+ yield '***************%s' % (lineterm,)
+ if group[-1][2] - group[0][1] >= 2:
+ yield '*** %d,%d ****%s' % (group[0][1]+1, group[-1][2], lineterm)
+ else:
+ yield '*** %d ****%s' % (group[-1][2], lineterm)
+ visiblechanges = [e for e in group if e[0] in ('replace', 'delete')]
+ if visiblechanges:
+ for tag, i1, i2, _, _ in group:
+ if tag != 'insert':
+ for line in a[i1:i2]:
+ yield prefixmap[tag] + line
+
+ if group[-1][4] - group[0][3] >= 2:
+ yield '--- %d,%d ----%s' % (group[0][3]+1, group[-1][4], lineterm)
+ else:
+ yield '--- %d ----%s' % (group[-1][4], lineterm)
+ visiblechanges = [e for e in group if e[0] in ('replace', 'insert')]
+ if visiblechanges:
+ for tag, _, _, j1, j2 in group:
+ if tag != 'delete':
+ for line in b[j1:j2]:
+ yield prefixmap[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 seperation)
+ 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"> Added </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)
+ # relace 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("&","&").replace(">",">").replace("<","<")
+
+ # make space non-breakable so they don't get compressed or line wrapped
+ text = text.replace(' ',' ').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> No Differences Found </td>']
+ tolist = fromlist
+ else:
+ fromlist = tolist = ['<td></td><td> Empty File </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',' ')
+
+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()
--- /dev/null
+++ b/sys/lib/python/dircache.py
@@ -1,0 +1,38 @@
+"""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."""
+
+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] + '/'
--- /dev/null
+++ b/sys/lib/python/dis.py
@@ -1,0 +1,223 @@
+"""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"] + _opcodes_all
+del _opcodes_all
+
+def dis(x=None):
+ """Disassemble classes, methods, functions, or code.
+
+ With no argument, disassemble the last traceback.
+
+ """
+ if x is None:
+ distb()
+ return
+ if type(x) is 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 type(x1) in (types.MethodType,
+ types.FunctionType,
+ types.CodeType,
+ types.ClassType):
+ print "Disassembly of %s:" % name
+ try:
+ dis(x1)
+ except TypeError, msg:
+ print "Sorry:", msg
+ 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 "%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] + ')',
+
+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] + ')',
+
+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()
--- /dev/null
+++ b/sys/lib/python/distutils/README
@@ -1,0 +1,22 @@
+This directory contains only a subset of the Distutils, specifically
+the Python modules in the 'distutils' and 'distutils.command'
+packages. This is all you need to distribute and install Python
+modules using the Distutils. There is also a separately packaged
+standalone version of the Distutils available for people who want to
+upgrade the Distutils without upgrading Python, available from the
+Distutils web page:
+
+ http://www.python.org/sigs/distutils-sig/
+
+The standalone version includes all of the code in this directory,
+plus documentation, test scripts, examples, etc.
+
+The Distutils documentation is divided into two documents, "Installing
+Python Modules", which explains how to install Python packages, and
+"Distributing Python Modules", which explains how to write setup.py
+files. Both documents are part of the standard Python documentation
+set, and are available from http://www.python.org/doc/current/ .
+
+ Greg Ward (gward@python.net)
+
+$Id: README 29650 2002-11-13 13:26:59Z akuchling $
--- /dev/null
+++ b/sys/lib/python/distutils/__init__.py
@@ -1,0 +1,23 @@
+"""distutils
+
+The main package for the Python Module Distribution Utilities. Normally
+used from a setup script as
+
+ from distutils.core import setup
+
+ setup (...)
+"""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: __init__.py 54641 2007-03-31 21:02:43Z marc-andre.lemburg $"
+
+# Distutils version
+#
+# Please coordinate with Marc-Andre Lemburg <mal@egenix.com> when adding
+# new features to distutils that would warrant bumping the version number.
+#
+# In general, major and minor version should loosely follow the Python
+# version number the distutils code was shipped with.
+#
+__version__ = "2.5.1"
--- /dev/null
+++ b/sys/lib/python/distutils/archive_util.py
@@ -1,0 +1,173 @@
+"""distutils.archive_util
+
+Utility functions for creating archive files (tarballs, zip files,
+that sort of thing)."""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: archive_util.py 37828 2004-11-10 22:23:15Z loewis $"
+
+import os
+from distutils.errors import DistutilsExecError
+from distutils.spawn import spawn
+from distutils.dir_util import mkpath
+from distutils import log
+
+def make_tarball (base_name, base_dir, compress="gzip",
+ verbose=0, dry_run=0):
+ """Create a (possibly compressed) tar file from all the files under
+ 'base_dir'. 'compress' must be "gzip" (the default), "compress",
+ "bzip2", or None. Both "tar" and the compression utility named by
+ 'compress' must be on the default program search path, so this is
+ probably Unix-specific. The output tar file will be named 'base_dir' +
+ ".tar", possibly plus the appropriate compression extension (".gz",
+ ".bz2" or ".Z"). Return the output filename.
+ """
+ # XXX GNU tar 1.13 has a nifty option to add a prefix directory.
+ # It's pretty new, though, so we certainly can't require it --
+ # but it would be nice to take advantage of it to skip the
+ # "create a tree of hardlinks" step! (Would also be nice to
+ # detect GNU tar to use its 'z' option and save a step.)
+
+ compress_ext = { 'gzip': ".gz",
+ 'bzip2': '.bz2',
+ 'compress': ".Z" }
+
+ # flags for compression program, each element of list will be an argument
+ compress_flags = {'gzip': ["-f9"],
+ 'compress': ["-f"],
+ 'bzip2': ['-f9']}
+
+ if compress is not None and compress not in compress_ext.keys():
+ raise ValueError, \
+ "bad value for 'compress': must be None, 'gzip', or 'compress'"
+
+ archive_name = base_name + ".tar"
+ mkpath(os.path.dirname(archive_name), dry_run=dry_run)
+ cmd = ["tar", "-cf", archive_name, base_dir]
+ spawn(cmd, dry_run=dry_run)
+
+ if compress:
+ spawn([compress] + compress_flags[compress] + [archive_name],
+ dry_run=dry_run)
+ return archive_name + compress_ext[compress]
+ else:
+ return archive_name
+
+# make_tarball ()
+
+
+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_dir' + ".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)
+
+ def visit (z, dirname, names):
+ for name in names:
+ path = os.path.normpath(os.path.join(dirname, name))
+ if os.path.isfile(path):
+ z.write(path, path)
+ log.info("adding '%s'" % path)
+
+ if not dry_run:
+ z = zipfile.ZipFile(zip_filename, "w",
+ compression=zipfile.ZIP_DEFLATED)
+
+ os.path.walk(base_dir, visit, z)
+ z.close()
+
+ return zip_filename
+
+# make_zipfile ()
+
+
+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):
+ for format in formats:
+ if not ARCHIVE_FORMATS.has_key(format):
+ return format
+ else:
+ return None
+
+def make_archive (base_name, format,
+ root_dir=None, base_dir=None,
+ verbose=0, dry_run=0):
+ """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.
+ """
+ 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
+ filename = apply(func, (base_name, base_dir), kwargs)
+
+ if root_dir is not None:
+ log.debug("changing back to '%s'", save_cwd)
+ os.chdir(save_cwd)
+
+ return filename
+
+# make_archive ()
--- /dev/null
+++ b/sys/lib/python/distutils/bcppcompiler.py
@@ -1,0 +1,398 @@
+"""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
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: bcppcompiler.py 37828 2004-11-10 22:23:15Z loewis $"
+
+
+import sys, os
+from distutils.errors import \
+ DistutilsExecError, DistutilsPlatformError, \
+ CompileError, LibError, LinkError, UnknownFileError
+from distutils.ccompiler import \
+ CCompiler, gen_preprocess_options, gen_lib_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()
--- /dev/null
+++ b/sys/lib/python/distutils/ccompiler.py
@@ -1,0 +1,1268 @@
+"""distutils.ccompiler
+
+Contains CCompiler, an abstract base class that defines the interface
+for the Distutils compiler abstraction model."""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: ccompiler.py 46331 2006-05-26 14:07:23Z bob.ippolito $"
+
+import sys, os, re
+from types import *
+from copy import copy
+from distutils.errors import *
+from distutils.spawn import spawn
+from distutils.file_util import move_file
+from distutils.dir_util import mkpath
+from distutils.dep_util import newer_pairwise, newer_group
+from distutils.util import split_quoted, execute
+from distutils import log
+
+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])
+
+ # __init__ ()
+
+
+ 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 not self.executables.has_key(key):
+ raise ValueError, \
+ "unknown executable '%s' for class %s" % \
+ (key, self.__class__.__name__)
+ self.set_executable(key, args[key])
+
+ # set_executables ()
+
+ def set_executable(self, key, value):
+ if type(value) is StringType:
+ 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 (type (defn) is TupleType and
+ (len (defn) == 1 or
+ (len (defn) == 2 and
+ (type (defn[1]) is StringType or defn[1] is None))) and
+ type (defn[0]) is StringType):
+ 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 = copy (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 = copy (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 = copy (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 = copy (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 = copy (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.
+
+ Merges _fix_compile_args() and _prep_compile().
+ """
+ if outdir is None:
+ outdir = self.output_dir
+ elif type(outdir) is not StringType:
+ raise TypeError, "'output_dir' must be a string or None"
+
+ if macros is None:
+ macros = self.macros
+ elif type(macros) is ListType:
+ 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 type(incdirs) in (ListType, TupleType):
+ 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)
+
+ # XXX should redo this code to eliminate skip_source entirely.
+ # XXX instead create build and issue skip messages inline
+
+ if self.force:
+ skip_source = {} # rebuild everything
+ for source in sources:
+ skip_source[source] = 0
+ elif depends is None:
+ # If depends is None, figure out which source files we
+ # have to recompile according to a simplistic check. We
+ # just compare the source and object file, no deep
+ # dependency checking involving header files.
+ skip_source = {} # rebuild everything
+ for source in sources: # no wait, rebuild nothing
+ skip_source[source] = 1
+
+ n_sources, n_objects = newer_pairwise(sources, objects)
+ for source in n_sources: # no really, only rebuild what's
+ skip_source[source] = 0 # out-of-date
+ else:
+ # If depends is a list of files, then do a different
+ # simplistic check. Assume that each object depends on
+ # its source and all files in the depends list.
+ skip_source = {}
+ # L contains all the depends plus a spot at the end for a
+ # particular source file
+ L = depends[:] + [None]
+ for i in range(len(objects)):
+ source = sources[i]
+ L[-1] = source
+ if newer_group(L, objects[i]):
+ skip_source[source] = 0
+ else:
+ skip_source[source] = 1
+
+ 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))
+ if skip_source[src]:
+ log.debug("skipping %s (%s up-to-date)", src, obj)
+ else:
+ 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 type (output_dir) is not StringType:
+ raise TypeError, "'output_dir' must be a string or None"
+
+ if macros is None:
+ macros = self.macros
+ elif type (macros) is ListType:
+ 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 type (include_dirs) in (ListType, TupleType):
+ 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
+
+ # _fix_compile_args ()
+
+
+ def _prep_compile(self, sources, output_dir, depends=None):
+ """Decide which souce files must be recompiled.
+
+ Determine the list of object files corresponding to 'sources',
+ and figure out which ones really need to be recompiled.
+ Return a list of all object files and a dictionary telling
+ which source files can be skipped.
+ """
+ # Get the list of expected output (object) files
+ objects = self.object_filenames(sources, output_dir=output_dir)
+ assert len(objects) == len(sources)
+
+ if self.force:
+ skip_source = {} # rebuild everything
+ for source in sources:
+ skip_source[source] = 0
+ elif depends is None:
+ # If depends is None, figure out which source files we
+ # have to recompile according to a simplistic check. We
+ # just compare the source and object file, no deep
+ # dependency checking involving header files.
+ skip_source = {} # rebuild everything
+ for source in sources: # no wait, rebuild nothing
+ skip_source[source] = 1
+
+ n_sources, n_objects = newer_pairwise(sources, objects)
+ for source in n_sources: # no really, only rebuild what's
+ skip_source[source] = 0 # out-of-date
+ else:
+ # If depends is a list of files, then do a different
+ # simplistic check. Assume that each object depends on
+ # its source and all files in the depends list.
+ skip_source = {}
+ # L contains all the depends plus a spot at the end for a
+ # particular source file
+ L = depends[:] + [None]
+ for i in range(len(objects)):
+ source = sources[i]
+ L[-1] = source
+ if newer_group(L, objects[i]):
+ skip_source[source] = 0
+ else:
+ skip_source[source] = 1
+
+ return objects, skip_source
+
+ # _prep_compile ()
+
+
+ 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 type (objects) not in (ListType, TupleType):
+ 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 type (output_dir) is not StringType:
+ 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 type (libraries) in (ListType, TupleType):
+ 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 type (library_dirs) in (ListType, TupleType):
+ 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 type (runtime_library_dirs) in (ListType, TupleType):
+ 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)
+
+ # _fix_lib_args ()
+
+
+ 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
+
+ # _need_link ()
+
+ 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 type(sources) is not ListType:
+ 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
+
+ # detect_language ()
+
+ # -- 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")
+ for incl in includes:
+ f.write("""#include "%s"\n""" % incl)
+ f.write("""\
+main (int argc, char **argv) {
+ %s();
+}
+""" % funcname)
+ 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, 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'),
+
+ # OS name mappings
+ ('posix', 'unix'),
+ ('nt', 'msvc'),
+ ('mac', 'mwerks'),
+
+ )
+
+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"),
+ 'mwerks': ('mwerkscompiler', 'MWerksCompiler',
+ "MetroWerks CodeWarrior"),
+ 'emx': ('emxccompiler', 'EMXCCompiler',
+ "EMX port of GNU C Compiler for OS/2"),
+ }
+
+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 (type (macro) is TupleType 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
+
+# gen_preprocess_options ()
+
+
+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 type(opt) is ListType:
+ lib_opts = lib_opts + 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:
+ 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
+
+# gen_lib_options ()
--- /dev/null
+++ b/sys/lib/python/distutils/cmd.py
@@ -1,0 +1,478 @@
+"""distutils.cmd
+
+Provides the Command class, the base class for the command classes
+in the distutils.command package.
+"""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: cmd.py 37828 2004-11-10 22:23:15Z loewis $"
+
+import sys, os, string, re
+from types import *
+from distutils.errors import *
+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
+
+ # __init__ ()
+
+
+ # 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()
+ print indent + header
+ indent = indent + " "
+ for (option, _, _) in self.user_options:
+ option = string.translate(option, longopt_xlate)
+ if option[-1] == "=":
+ option = option[:-1]
+ value = getattr(self, option)
+ print indent + "%s = %s" % (option, value)
+
+
+ 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 type(val) is not StringType:
+ 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 type(val) is StringType:
+ setattr(self, option, re.split(r',\s*|\s+', val))
+ else:
+ if type(val) is ListType:
+ types = map(type, val)
+ ok = (types == [StringType] * len(val))
+ 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):
+ sys.stderr.write("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 respectin 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):
+ return archive_util.make_archive(
+ base_name, format, root_dir, base_dir, dry_run=self.dry_run)
+
+
+ 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 exec_msg is None:
+ exec_msg = "generating %s from %s" % \
+ (outfile, string.join(infiles, ', '))
+ if skip_msg is None:
+ skip_msg = "skipping %s (inputs unchanged)" % outfile
+
+
+ # Allow 'infiles' to be a single string
+ if type(infiles) is StringType:
+ infiles = (infiles,)
+ elif type(infiles) not in (ListType, TupleType):
+ raise TypeError, \
+ "'infiles' must be a string, or a list or tuple of strings"
+
+ # 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)
+
+ # make_file ()
+
+# class Command
+
+
+# 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
+
+
+if __name__ == "__main__":
+ print "ok"
--- /dev/null
+++ b/sys/lib/python/distutils/command/__init__.py
@@ -1,0 +1,33 @@
+"""distutils.command
+
+Package containing implementation of all the standard Distutils
+commands."""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: __init__.py 37828 2004-11-10 22:23:15Z loewis $"
+
+__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',
+ # 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
+ ]
--- /dev/null
+++ b/sys/lib/python/distutils/command/bdist.py
@@ -1,0 +1,150 @@
+"""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 37828 2004-11-10 22:23:15Z loewis $"
+
+import os, string
+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',
+ '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:
+ self.plat_name = get_platform()
+
+ # '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
--- /dev/null
+++ b/sys/lib/python/distutils/command/bdist_dumb.py
@@ -1,0 +1,135 @@
+"""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)."""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: bdist_dumb.py 38697 2005-03-23 18:54:36Z loewis $"
+
+import os
+from distutils.core import Command
+from distutils.util import get_platform
+from distutils.dir_util import create_tree, remove_tree, ensure_relative
+from distutils.errors import *
+from distutils.sysconfig import get_python_version
+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)"),
+ ]
+
+ boolean_options = ['keep-temp', 'skip-build', 'relative']
+
+ default_format = { 'posix': '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
+
+ # initialize_options()
+
+
+ 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'))
+
+ # finalize_options()
+
+
+ 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)
+ 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)
+
+ # run()
+
+# class bdist_dumb
--- /dev/null
+++ b/sys/lib/python/distutils/command/bdist_msi.py
@@ -1,0 +1,639 @@
+# -*- coding: iso-8859-1 -*-
+# Copyright (C) 2005, 2006 Martin v. 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, string
+from distutils.core import Command
+from distutils.util import get_platform
+from distutils.dir_util import remove_tree
+from distutils.sysconfig import get_python_version
+from distutils.version import StrictVersion
+from distutils.errors import DistutilsOptionError
+from distutils import log
+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
+ bmwidth = 152*ruler/328
+ #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"),
+ ('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']
+
+ def initialize_options (self):
+ self.bdist_dir = 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 = 0
+ self.install_script = None
+ self.pre_install_script = 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, 'msi')
+ short_version = get_python_version()
+ if 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.target_version = short_version
+
+ self.set_undefined_options('bdist', ('dist_dir', 'dist_dir'))
+
+ 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" % (get_platform(), 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)
+ product_name = "Python %s %s" % (self.target_version,
+ self.distribution.get_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'):
+ self.distribution.dist_files.append(('bdist_msi', self.target_version, fullname))
+
+ 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")
+ f = Feature(db, "default", "Default Feature", "Everything", 1, directory="TARGETDIR")
+ f.set_current()
+ rootdir = os.path.abspath(self.bdist_dir)
+ root = Directory(db, cab, None, rootdir, "TARGETDIR", "SourceDir")
+ db.Commit()
+ todo = [root]
+ while todo:
+ dir = todo.pop()
+ for file in os.listdir(dir.absolute):
+ afile = os.path.join(dir.absolute, file)
+ if os.path.isdir(afile):
+ newdir = Directory(db, cab, dir, file, file, "%s|%s" % (dir.make_short(file), file))
+ todo.append(newdir)
+ else:
+ key = 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
+
+ cab.commit(db)
+
+ def add_find_python(self):
+ """Adds code to the installer to compute the location of Python.
+ Properties PYTHON.MACHINE, PYTHON.USER, PYTHONDIR and PYTHON will be set
+ in both the execute and UI sequences; PYTHONDIR will be set from
+ PYTHON.USER if defined, else from PYTHON.MACHINE.
+ PYTHON is PYTHONDIR\python.exe"""
+ install_path = r"SOFTWARE\Python\PythonCore\%s\InstallPath" % self.target_version
+ add_data(self.db, "RegLocator",
+ [("python.machine", 2, install_path, None, 2),
+ ("python.user", 1, install_path, None, 2)])
+ add_data(self.db, "AppSearch",
+ [("PYTHON.MACHINE", "python.machine"),
+ ("PYTHON.USER", "python.user")])
+ add_data(self.db, "CustomAction",
+ [("PythonFromMachine", 51+256, "PYTHONDIR", "[PYTHON.MACHINE]"),
+ ("PythonFromUser", 51+256, "PYTHONDIR", "[PYTHON.USER]"),
+ ("PythonExe", 51+256, "PYTHON", "[PYTHONDIR]\\python.exe"),
+ ("InitialTargetDir", 51+256, "TARGETDIR", "[PYTHONDIR]")])
+ add_data(self.db, "InstallExecuteSequence",
+ [("PythonFromMachine", "PYTHON.MACHINE", 401),
+ ("PythonFromUser", "PYTHON.USER", 402),
+ ("PythonExe", None, 403),
+ ("InitialTargetDir", 'TARGETDIR=""', 404),
+ ])
+ add_data(self.db, "InstallUISequence",
+ [("PythonFromMachine", "PYTHON.MACHINE", 401),
+ ("PythonFromUser", "PYTHON.USER", 402),
+ ("PythonExe", None, 403),
+ ("InitialTargetDir", 'TARGETDIR=""', 404),
+ ])
+
+ def add_scripts(self):
+ if self.install_script:
+ add_data(self.db, "CustomAction",
+ [("install_script", 50, "PYTHON", self.install_script_key)])
+ add_data(self.db, "InstallExecuteSequence",
+ [("install_script", "NOT Installed", 6800)])
+ 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
+ track_disk_space = 32
+
+ # 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.
+ ("SelectDirectoryDlg", "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")
+
+ #####################################################################
+ # Target directory selection
+ seldlg = PyDialog(db, "SelectDirectoryDlg", x, y, w, h, modal, title,
+ "Next", "Next", "Cancel")
+ seldlg.title("Select Destination Directory")
+
+ version = sys.version[:3]+" "
+ seldlg.text("Hint", 15, 30, 300, 40, 3,
+ "The destination directory should contain a Python %sinstallation" % version)
+
+ seldlg.back("< Back", None, active=0)
+ c = seldlg.next("Next >", "Cancel")
+ c.event("SetTargetPath", "TARGETDIR", ordering=1)
+ c.event("SpawnWaitDialog", "WaitForCostingDlg", ordering=2)
+ c.event("EndDialog", "Return", ordering=3)
+
+ c = seldlg.cancel("Cancel", "DirectoryCombo")
+ c.event("SpawnDialog", "CancelDlg")
+
+ seldlg.control("DirectoryCombo", "DirectoryCombo", 15, 70, 272, 80, 393219,
+ "TARGETDIR", None, "DirectoryList", None)
+ seldlg.control("DirectoryList", "DirectoryList", 15, 90, 308, 136, 3, "TARGETDIR",
+ None, "PathEdit", None)
+ seldlg.control("PathEdit", "PathEdit", 15, 230, 306, 16, 3, "TARGETDIR", None, "Next", None)
+ c = seldlg.pushbutton("Up", 306, 70, 18, 18, 3, "Up", None)
+ c.event("DirectoryListUp", "0")
+ c = seldlg.pushbutton("NewDir", 324, 70, 30, 18, 3, "New", None)
+ c.event("DirectoryListNew", "0")
+
+ #####################################################################
+ # 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
+ installer_name = os.path.join(self.dist_dir,
+ "%s.win32-py%s.msi" %
+ (fullname, self.target_version))
+ return installer_name
--- /dev/null
+++ b/sys/lib/python/distutils/command/bdist_rpm.py
@@ -1,0 +1,564 @@
+"""distutils.command.bdist_rpm
+
+Implements the Distutils 'bdist_rpm' command (create RPM source and binary
+distributions)."""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: bdist_rpm.py 52742 2006-11-12 18:56:18Z martin.v.loewis $"
+
+import sys, os, string
+import glob
+from types import *
+from distutils.core import Command
+from distutils.debug import DEBUG
+from distutils.util import get_platform
+from distutils.file_util import write_file
+from distutils.errors import *
+from distutils.sysconfig import get_python_version
+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"),
+ ]
+
+ boolean_options = ['keep-temp', 'use-rpm-opt-flags', 'rpm3-mode',
+ 'no-autoreq']
+
+ 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
+
+ # 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 type(self.doc_files) is ListType:
+ 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')
+ 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)
+ 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))
+
+ self.spawn(rpm_cmd)
+
+ if not self.dry_run:
+ 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)
+
+ 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)
+ # 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 type(val) is ListType:
+ 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.
+
+ script_options = [
+ ('prep', 'prep_script', "%setup -n %{name}-%{unmangled_version}"),
+ ('build', 'build_script', def_build),
+ ('install', 'install_script',
+ ("%s install "
+ "--root=$RPM_BUILD_ROOT "
+ "--record=INSTALLED_FILES") % def_setup_call),
+ ('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
--- /dev/null
+++ b/sys/lib/python/distutils/command/bdist_wininst.py
@@ -1,0 +1,328 @@
+"""distutils.command.bdist_wininst
+
+Implements the Distutils 'bdist_wininst' command: create a windows installer
+exe-program."""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: bdist_wininst.py 38697 2005-03-23 18:54:36Z loewis $"
+
+import sys, os, string
+from distutils.core import Command
+from distutils.util import get_platform
+from distutils.dir_util import create_tree, remove_tree
+from distutils.errors import *
+from distutils.sysconfig import get_python_version
+from distutils import log
+
+class bdist_wininst (Command):
+
+ description = "create an executable installer for MS Windows"
+
+ user_options = [('bdist-dir=', None,
+ "temporary directory for creating the distribution"),
+ ('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"),
+ ]
+
+ boolean_options = ['keep-temp', 'no-target-compile', 'no-target-optimize',
+ 'skip-build']
+
+ def initialize_options (self):
+ self.bdist_dir = 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 = 0
+ self.install_script = None
+ self.pre_install_script = None
+
+ # initialize_options()
+
+
+ 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, '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'))
+
+ 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_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" % (get_platform(), 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)
+
+ 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.win32-py%s.exe" %
+ (fullname, self.target_version))
+ else:
+ installer_name = os.path.join(self.dist_dir,
+ "%s.win32.exe" % fullname)
+ 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"
+ 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?
+ filename = os.path.join(directory, "wininst-%s.exe" % bv)
+ return open(filename, "rb").read()
+# class bdist_wininst
--- /dev/null
+++ b/sys/lib/python/distutils/command/build.py
@@ -1,0 +1,136 @@
+"""distutils.command.build
+
+Implements the Distutils 'build' command."""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: build.py 37828 2004-11-10 22:23:15Z loewis $"
+
+import sys, os
+from distutils.core import Command
+from distutils.util import get_platform
+
+
+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"),
+ ('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.debug = None
+ self.force = 0
+ self.executable = None
+
+ def finalize_options (self):
+
+ plat_specifier = ".%s-%s" % (get_platform(), sys.version[0:3])
+
+ # '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)
+ # finalize_options ()
+
+
+ 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),
+ ]
+
+# class build
--- /dev/null
+++ b/sys/lib/python/distutils/command/build_clib.py
@@ -1,0 +1,238 @@
+"""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."""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: build_clib.py 37828 2004-11-10 22:23:15Z loewis $"
+
+
+# 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, string
+from types import *
+from distutils.core import Command
+from distutils.errors import *
+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
+
+ # initialize_options()
+
+
+ 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 type(self.include_dirs) is StringType:
+ self.include_dirs = string.split(self.include_dirs,
+ os.pathsep)
+
+ # XXX same as for build_ext -- what about 'self.define' and
+ # 'self.undef' ?
+
+ # finalize_options()
+
+
+ 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)
+
+ # run()
+
+
+ def check_library_list (self, libraries):
+ """Ensure that the list of libraries (presumably provided as a
+ command option 'libraries') is valid, i.e. 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."""
+
+ # Yechh, blecch, ackk: this is ripped straight out of build_ext.py,
+ # with only names changed to protect the innocent!
+
+ if type(libraries) is not ListType:
+ raise DistutilsSetupError, \
+ "'libraries' option must be a list of tuples"
+
+ for lib in libraries:
+ if type(lib) is not TupleType and len(lib) != 2:
+ raise DistutilsSetupError, \
+ "each element of 'libraries' must a 2-tuple"
+
+ if type(lib[0]) is not StringType:
+ raise DistutilsSetupError, \
+ "first element of each tuple in 'libraries' " + \
+ "must be a string (the library name)"
+ if '/' in lib[0] or (os.sep != '/' and os.sep in lib[0]):
+ raise DistutilsSetupError, \
+ ("bad library name '%s': " +
+ "may not contain directory separators") % \
+ lib[0]
+
+ if type(lib[1]) is not DictionaryType:
+ raise DistutilsSetupError, \
+ "second element of each tuple in 'libraries' " + \
+ "must be a dictionary (build info)"
+ # for lib
+
+ # check_library_list ()
+
+
+ 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
+
+ # get_library_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
+ type(sources) not in (ListType, TupleType) ):
+ 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
+ # get_source_files ()
+
+
+ def build_libraries (self, libraries):
+
+ for (lib_name, build_info) in libraries:
+ sources = build_info.get('sources')
+ if sources is None or type(sources) not in (ListType, TupleType):
+ 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)
+
+ # for libraries
+
+ # build_libraries ()
+
+# class build_lib
--- /dev/null
+++ b/sys/lib/python/distutils/command/build_ext.py
@@ -1,0 +1,716 @@
+"""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: build_ext.py 54332 2007-03-13 10:19:35Z georg.brandl $"
+
+import sys, os, string, re
+from types import *
+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 import log
+
+# 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)"),
+ ('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"),
+ ]
+
+ boolean_options = ['inplace', 'debug', 'force', 'swig-cpp']
+
+ help_options = [
+ ('help-compiler', None,
+ "list available compilers", show_compilers),
+ ]
+
+ def initialize_options (self):
+ self.extensions = None
+ self.build_lib = 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
+
+ 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'))
+
+ 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 type(self.include_dirs) is StringType:
+ self.include_dirs = string.split(self.include_dirs, 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)
+
+ if type(self.libraries) is StringType:
+ self.libraries = [self.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':
+ 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'))
+ self.library_dirs.append(os.path.join(sys.exec_prefix, 'PCBuild'))
+
+ # 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 with a shared Python library,
+ # Python's library directory must be appended to library_dirs
+ if (sys.platform.startswith('linux') or sys.platform.startswith('gnu')) \
+ 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 = string.split(self.define, ',')
+ 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 = string.split(self.undef, ',')
+
+ if self.swig_opts is None:
+ self.swig_opts = []
+ else:
+ self.swig_opts = self.swig_opts.split(' ')
+
+ # finalize_options ()
+
+
+ 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)
+
+ # 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()
+
+ # run ()
+
+
+ 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 type(extensions) is not ListType:
+ raise DistutilsSetupError, \
+ "'ext_modules' option must be a list of Extension instances"
+
+ for i in range(len(extensions)):
+ ext = extensions[i]
+ if isinstance(ext, Extension):
+ continue # OK! (assume type-checking done
+ # by Extension constructor)
+
+ (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 type(ext) is not TupleType and len(ext) != 2:
+ raise DistutilsSetupError, \
+ ("each element of 'ext_modules' option must be an "
+ "Extension instance or 2-tuple")
+
+ if not (type(ext_name) is StringType 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 type(build_info) is not DictionaryType:
+ 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 build_info.has_key('def_file'):
+ 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 (type(macro) is TupleType and
+ 1 <= len(macro) <= 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
+
+ # for extensions
+
+ # check_extensions_list ()
+
+
+ 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:
+ fullname = self.get_ext_fullname(ext.name)
+ outputs.append(os.path.join(self.build_lib,
+ self.get_ext_filename(fullname)))
+ return outputs
+
+ # get_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)
+
+ fullname = self.get_ext_fullname(ext.name)
+ if self.inplace:
+ # ignore build-lib -- put the compiled extension into
+ # the source tree along with pure Python modules
+
+ modpath = string.split(fullname, '.')
+ package = string.join(modpath[0:-1], '.')
+ base = modpath[-1]
+
+ build_py = self.get_finalized_command('build_py')
+ package_dir = build_py.get_package_dir(package)
+ ext_filename = os.path.join(package_dir,
+ self.get_ext_filename(base))
+ else:
+ ext_filename = os.path.join(self.build_lib,
+ self.get_ext_filename(fullname))
+ depends = sources + ext.depends
+ if not (self.force or newer_group(depends, ext_filename, '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_filename,
+ 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):
+ 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_fullname (self, ext_name):
+ 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 apply(os.path.join, ext_path) + '_d' + so_ext
+ return apply(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" + string.split(ext.name,'.')[-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
+
+ 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
--- /dev/null
+++ b/sys/lib/python/distutils/command/build_py.py
@@ -1,0 +1,435 @@
+"""distutils.command.build_py
+
+Implements the Distutils 'build_py' command."""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: build_py.py 37828 2004-11-10 22:23:15Z loewis $"
+
+import sys, string, os
+from types import *
+from glob import glob
+
+from distutils.core import Command
+from distutils.errors import *
+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 type(self.optimize) is not IntType:
+ 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))
+
+ # run ()
+
+ 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 = 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"""
+ lastdir = None
+ 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 = string.split(package, '.')
+
+ if not self.package_dir:
+ if path:
+ return apply(os.path.join, path)
+ else:
+ return ''
+ else:
+ tail = []
+ while path:
+ try:
+ pdir = self.package_dir[string.join(path, '.')]
+ except KeyError:
+ tail.insert(0, path[-1])
+ del path[-1]
+ else:
+ tail.insert(0, pdir)
+ return apply(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 apply(os.path.join, tail)
+ else:
+ return ''
+
+ # get_package_dir ()
+
+
+ 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
+
+ # check_package ()
+
+
+ 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 0
+ else:
+ return 1
+
+ # check_module ()
+
+
+ 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 = string.split(module, '.')
+ package = string.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
+
+ # find_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
+
+ # find_all_modules ()
+
+
+ def get_source_files (self):
+
+ modules = self.find_all_modules()
+ filenames = []
+ for module in modules:
+ filenames.append(module[-1])
+
+ return filenames
+
+
+ def get_module_outfile (self, build_dir, package, module):
+ outfile_path = [build_dir] + list(package) + [module + ".py"]
+ return apply(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 = string.split(package, '.')
+ 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 type(package) is StringType:
+ package = string.split(package, '.')
+ elif type(package) not in (ListType, TupleType):
+ 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)
+
+ # build_modules ()
+
+
+ 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)
+
+ # build_packages ()
+
+
+ def byte_compile (self, files):
+ 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)
+
+# class build_py
--- /dev/null
+++ b/sys/lib/python/distutils/command/build_scripts.py
@@ -1,0 +1,131 @@
+"""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 37828 2004-11-10 22:23:15Z loewis $"
+
+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 self.dry_run:
+ outf = open(outfile, "w")
+ if not sysconfig.python_build:
+ outf.write("#!%s%s\n" %
+ (self.executable,
+ post_interp))
+ else:
+ outf.write("#!%s%s\n" %
+ (os.path.join(
+ sysconfig.get_config_var("BINDIR"),
+ "python" + sysconfig.get_config_var("EXE")),
+ post_interp))
+ outf.writelines(f.readlines())
+ outf.close()
+ if f:
+ f.close()
+ else:
+ f.close()
+ self.copy_file(script, outfile)
+
+ if os.name == 'posix':
+ 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
--- /dev/null
+++ b/sys/lib/python/distutils/command/clean.py
@@ -1,0 +1,82 @@
+"""distutils.command.clean
+
+Implements the Distutils 'clean' command."""
+
+# contributed by Bastian Kleineidam <calvin@cs.uni-sb.de>, added 2000-03-18
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: clean.py 38532 2005-03-03 08:12:27Z loewis $"
+
+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
--- /dev/null
+++ b/sys/lib/python/distutils/command/command_template
@@ -1,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
--- /dev/null
+++ b/sys/lib/python/distutils/command/config.py
@@ -1,0 +1,368 @@
+"""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".
+"""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: config.py 37828 2004-11-10 22:23:15Z loewis $"
+
+import sys, os, string, re
+from types import *
+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.define = None
+ #self.undef = 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 type(self.include_dirs) is StringType:
+ self.include_dirs = string.split(self.include_dirs, os.pathsep)
+
+ if self.libraries is None:
+ self.libraries = []
+ elif type(self.libraries) is StringType:
+ self.libraries = [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)
+
+
+ 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", string.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 type(pattern) is StringType:
+ 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 = string.join(body, "\n") + "\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)
+
+
+# class config
+
+
+def dump_file (filename, head=None):
+ if head is None:
+ print filename + ":"
+ else:
+ print head
+
+ file = open(filename)
+ sys.stdout.write(file.read())
+ file.close()
--- /dev/null
+++ b/sys/lib/python/distutils/command/install.py
@@ -1,0 +1,607 @@
+"""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',
+ }
+ }
+
+# 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
--- /dev/null
+++ b/sys/lib/python/distutils/command/install_data.py
@@ -1,0 +1,85 @@
+"""distutils.command.install_data
+
+Implements the Distutils 'install_data' command, for installing
+platform-independent data files."""
+
+# contributed by Bastian Kleineidam
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: install_data.py 37828 2004-11-10 22:23:15Z loewis $"
+
+import os
+from types import StringType
+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 type(f) is StringType:
+ # 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
--- /dev/null
+++ b/sys/lib/python/distutils/command/install_egg_info.py
@@ -1,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('-','_')
--- /dev/null
+++ b/sys/lib/python/distutils/command/install_headers.py
@@ -1,0 +1,53 @@
+"""distutils.command.install_headers
+
+Implements the Distutils 'install_headers' command, to install C/C++ header
+files to the Python include directory."""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: install_headers.py 37828 2004-11-10 22:23:15Z loewis $"
+
+import os
+from distutils.core import Command
+
+
+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
--- /dev/null
+++ b/sys/lib/python/distutils/command/install_lib.py
@@ -1,0 +1,223 @@
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: install_lib.py 37946 2004-12-02 20:14:16Z lemburg $"
+
+import sys, os, string
+from types import IntType
+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 type(self.optimize) is not IntType:
+ 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):
+
+ # 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)
+
+ # run ()
+
+
+ # -- 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):
+ 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
+
+ # _mutate_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
+
+ # get_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
+
+# class install_lib
--- /dev/null
+++ b/sys/lib/python/distutils/command/install_scripts.py
@@ -1,0 +1,66 @@
+"""distutils.command.install_scripts
+
+Implements the Distutils 'install_scripts' command, for installing
+Python scripts."""
+
+# contributed by Bastian Kleineidam
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: install_scripts.py 37828 2004-11-10 22:23:15Z loewis $"
+
+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 os.name == 'posix':
+ # 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
--- /dev/null
+++ b/sys/lib/python/distutils/command/register.py
@@ -1,0 +1,294 @@
+"""distutils.command.register
+
+Implements the Distutils 'register' command (register with the repository).
+"""
+
+# created 2002/10/21, Richard Jones
+
+__revision__ = "$Id: register.py 52243 2006-10-09 17:13:26Z andrew.kuchling $"
+
+import sys, os, string, urllib2, getpass, urlparse
+import StringIO, ConfigParser
+
+from distutils.core import Command
+from distutils.errors import *
+
+class register(Command):
+
+ description = ("register the distribution with the Python package index")
+
+ DEFAULT_REPOSITORY = 'http://www.python.org/pypi'
+
+ user_options = [
+ ('repository=', 'r',
+ "url of repository [default: %s]"%DEFAULT_REPOSITORY),
+ ('list-classifiers', None,
+ 'list the valid Trove classifiers'),
+ ('show-response', None,
+ 'display full response text from server'),
+ ]
+ boolean_options = ['verify', 'show-response', 'list-classifiers']
+
+ def initialize_options(self):
+ self.repository = None
+ self.show_response = 0
+ self.list_classifiers = 0
+
+ def finalize_options(self):
+ if self.repository is None:
+ self.repository = self.DEFAULT_REPOSITORY
+
+ def run(self):
+ self.check_metadata()
+ if self.dry_run:
+ self.verify_metadata()
+ elif self.list_classifiers:
+ self.classifiers()
+ else:
+ self.send_metadata()
+
+ 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")
+
+ def classifiers(self):
+ ''' Fetch the list of classifiers from the server.
+ '''
+ response = urllib2.urlopen(self.repository+'?:action=list_classifiers')
+ print 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'))
+ print '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
+ [server-login] containing username and password entries (both
+ in clear text). Eg:
+
+ [server-login]
+ 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.
+
+ '''
+ choice = 'x'
+ username = password = ''
+
+ # see if we can short-cut and get the username/password from the
+ # config
+ config = None
+ if os.environ.has_key('HOME'):
+ rc = os.path.join(os.environ['HOME'], '.pypirc')
+ if os.path.exists(rc):
+ print 'Using PyPI login from %s'%rc
+ config = ConfigParser.ConfigParser()
+ config.read(rc)
+ username = config.get('server-login', 'username')
+ password = config.get('server-login', 'password')
+ choice = '1'
+
+ # get the user's login info
+ choices = '1 2 3 4'.split()
+ while choice not in choices:
+ print '''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]: ''',
+ 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('pypi', 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)
+ print 'Server response (%s): %s'%(code, result)
+
+ # possibly save the login
+ if os.environ.has_key('HOME') and config is None and code == 200:
+ rc = os.path.join(os.environ['HOME'], '.pypirc')
+ print 'I can store your PyPI login so future submissions will be faster.'
+ print '(the login will be stored in %s)'%rc
+ 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':
+ f = open(rc, 'w')
+ f.write('[server-login]\nusername:%s\npassword:%s\n'%(
+ username, password))
+ f.close()
+ try:
+ os.chmod(rc, 0600)
+ except:
+ pass
+ 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:
+ print 'Server response (%s): %s'%(code, result)
+ else:
+ print 'You will receive an email shortly.'
+ print '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)
+ print '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.
+ '''
+
+ # Build up the MIME payload for the urllib2 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 type(value) not in (type([]), type( () )):
+ value = [value]
+ for value in value:
+ value = unicode(value).encode("utf-8")
+ body.write(sep_boundary)
+ body.write('\nContent-Disposition: form-data; name="%s"'%key)
+ 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()
+
+ # 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:
+ print '-'*75, data, '-'*75
+ return result
--- /dev/null
+++ b/sys/lib/python/distutils/command/sdist.py
@@ -1,0 +1,465 @@
+"""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 38697 2005-03-23 18:54:36Z 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',
+ '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 and .svn 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)/.*', 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)
+ while 1:
+ line = manifest.readline()
+ if line == '': # end of file
+ break
+ if line[-1] == '\n':
+ line = line[0:-1]
+ self.filelist.append(line)
+
+ # 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
--- /dev/null
+++ b/sys/lib/python/distutils/command/upload.py
@@ -1,0 +1,199 @@
+"""distutils.command.upload
+
+Implements the Distutils 'upload' subcommand (upload package to PyPI)."""
+
+from distutils.errors import *
+from distutils.core import Command
+from distutils.spawn import spawn
+from distutils import log
+from hashlib import md5
+import os
+import socket
+import platform
+import ConfigParser
+import httplib
+import base64
+import urlparse
+import cStringIO as StringIO
+
+class upload(Command):
+
+ description = "upload binary package to PyPI"
+
+ DEFAULT_REPOSITORY = 'http://www.python.org/pypi'
+
+ user_options = [
+ ('repository=', 'r',
+ "url of repository [default: %s]" % DEFAULT_REPOSITORY),
+ ('show-response', None,
+ 'display full response text from server'),
+ ('sign', 's',
+ 'sign files to upload using gpg'),
+ ('identity=', 'i', 'GPG identity used to sign files'),
+ ]
+ boolean_options = ['show-response', 'sign']
+
+ def initialize_options(self):
+ self.username = ''
+ self.password = ''
+ self.repository = ''
+ self.show_response = 0
+ self.sign = False
+ self.identity = None
+
+ def finalize_options(self):
+ if self.identity and not self.sign:
+ raise DistutilsOptionError(
+ "Must use --sign for --identity to have meaning"
+ )
+ if os.environ.has_key('HOME'):
+ rc = os.path.join(os.environ['HOME'], '.pypirc')
+ if os.path.exists(rc):
+ self.announce('Using PyPI login from %s' % rc)
+ config = ConfigParser.ConfigParser({
+ 'username':'',
+ 'password':'',
+ 'repository':''})
+ config.read(rc)
+ if not self.repository:
+ self.repository = config.get('server-login', 'repository')
+ if not self.username:
+ self.username = config.get('server-login', 'username')
+ if not self.password:
+ self.password = config.get('server-login', 'password')
+ if not self.repository:
+ self.repository = self.DEFAULT_REPOSITORY
+
+ 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):
+ # 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
+ content = open(filename,'rb').read()
+ 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 " + base64.encodestring(self.username + ":" + self.password).strip()
+
+ # 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 type(value) != type([]):
+ value = [value]
+ for value in value:
+ if type(value) is tuple:
+ fn = ';filename="%s"' % value[0]
+ value = value[1]
+ else:
+ fn = ""
+ value = str(value)
+ 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
+ # We can't use urllib2 since we need to send the Basic
+ # auth right with the first request
+ schema, netloc, url, params, query, fragments = \
+ urlparse.urlparse(self.repository)
+ assert not params and not query and not fragments
+ if schema == 'http':
+ http = httplib.HTTPConnection(netloc)
+ elif schema == 'https':
+ http = httplib.HTTPSConnection(netloc)
+ else:
+ raise AssertionError, "unsupported schema "+schema
+
+ data = ''
+ loglevel = log.INFO
+ try:
+ http.connect()
+ http.putrequest("POST", url)
+ http.putheader('Content-type',
+ 'multipart/form-data; boundary=%s'%boundary)
+ http.putheader('Content-length', str(len(body)))
+ http.putheader('Authorization', auth)
+ http.endheaders()
+ http.send(body)
+ except socket.error, e:
+ self.announce(str(e), log.ERROR)
+ return
+
+ r = http.getresponse()
+ if r.status == 200:
+ self.announce('Server response (%s): %s' % (r.status, r.reason),
+ log.INFO)
+ else:
+ self.announce('Upload failed (%s): %s' % (r.status, r.reason),
+ log.ERROR)
+ if self.show_response:
+ print '-'*75, r.read(), '-'*75
--- /dev/null
+++ b/sys/lib/python/distutils/core.py
@@ -1,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.
+"""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: core.py 38672 2005-03-20 22:19:47Z fdrake $"
+
+import sys, os
+from types import *
+
+from distutils.debug import DEBUG
+from distutils.errors import *
+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.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 % vars()
+
+
+# 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 not attrs.has_key('script_name'):
+ attrs['script_name'] = os.path.basename(sys.argv[0])
+ if not attrs.has_key('script_args'):
+ 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 attrs.has_key('name'):
+ 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; 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
+
+# setup ()
+
+
+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 = {}
+ l = {}
+ try:
+ try:
+ sys.argv[0] = script_name
+ if script_args is not None:
+ sys.argv[1:] = script_args
+ execfile(script_name, g, l)
+ 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?
+ #print "_setup_distribution:", _setup_distribution
+ return _setup_distribution
+
+# run_setup ()
--- /dev/null
+++ b/sys/lib/python/distutils/cygwinccompiler.py
@@ -1,0 +1,441 @@
+"""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: cygwinccompiler.py 37828 2004-11-10 22:23:15Z loewis $"
+
+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 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:
+ self.dll_libraries=[]
+ # Include the appropriate MSVC runtime library if Python was built
+ # with MSVC 7.0 or 7.1.
+ 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
+ self.dll_libraries = ['msvcr70']
+ elif msc_ver == '1310':
+ # MSVC 7.1
+ self.dll_libraries = ['msvcr71']
+
+ # __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 7.1.
+ 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
+ self.dll_libraries = ['msvcr70']
+ elif msc_ver == '1310':
+ # MSVC 7.1
+ self.dll_libraries = ['msvcr71']
+
+ # __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)
+ s = f.read()
+ 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 StrictVersion
+ 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 = StrictVersion(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 = StrictVersion(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 = StrictVersion(result.group(1))
+ else:
+ dllwrap_version = None
+ else:
+ dllwrap_version = None
+ return (gcc_version, ld_version, dllwrap_version)
--- /dev/null
+++ b/sys/lib/python/distutils/debug.py
@@ -1,0 +1,9 @@
+import os
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: debug.py 37828 2004-11-10 22:23:15Z loewis $"
+
+# If DISTUTILS_DEBUG is anything other than the empty string, we run in
+# debug mode.
+DEBUG = os.environ.get('DISTUTILS_DEBUG')
--- /dev/null
+++ b/sys/lib/python/distutils/dep_util.py
@@ -1,0 +1,95 @@
+"""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."""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: dep_util.py 37828 2004-11-10 22:23:15Z loewis $"
+
+import os
+from distutils.errors import DistutilsFileError
+
+
+def newer (source, target):
+ """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.
+ """
+ if not os.path.exists(source):
+ raise DistutilsFileError, "file '%s' does not exist" % source
+ if not os.path.exists(target):
+ return 1
+
+ from stat import ST_MTIME
+ mtime1 = os.stat(source)[ST_MTIME]
+ mtime2 = os.stat(target)[ST_MTIME]
+
+ return mtime1 > mtime2
+
+# newer ()
+
+
+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 i in range(len(sources)):
+ if newer(sources[i], targets[i]):
+ n_sources.append(sources[i])
+ n_targets.append(targets[i])
+
+ return (n_sources, n_targets)
+
+# newer_pairwise ()
+
+
+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 1
+
+ # 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.
+ from stat import ST_MTIME
+ 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 1 # out-of-date
+
+ source_mtime = os.stat(source)[ST_MTIME]
+ if source_mtime > target_mtime:
+ return 1
+ else:
+ return 0
+
+# newer_group ()
--- /dev/null
+++ b/sys/lib/python/distutils/dir_util.py
@@ -1,0 +1,227 @@
+"""distutils.dir_util
+
+Utility functions for manipulating directories and directory trees."""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: dir_util.py 39416 2005-08-26 15:20:46Z tim_one $"
+
+import os, sys
+from types import *
+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=0, 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, StringTypes):
+ 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):
+ #print "splitting '%s': " % head,
+ (head, tail) = os.path.split(head)
+ #print "to ('%s','%s')" % (head, tail)
+ tails.insert(0, tail) # push next higher dir onto stack
+
+ #print "stack of tails:", tails
+
+ # 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
+
+ log.info("creating %s", head)
+
+ if not dry_run:
+ try:
+ os.mkdir(head)
+ created_dirs.append(head)
+ except OSError, exc:
+ raise DistutilsFileError, \
+ "could not create '%s': %s" % (head, exc[-1])
+
+ _path_created[abs_head] = 1
+ return created_dirs
+
+# mkpath ()
+
+
+def create_tree (base_dir, files, mode=0777, verbose=0, 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, dry_run=dry_run)
+
+# create_tree ()
+
+
+def copy_tree (src, dst,
+ preserve_mode=1,
+ preserve_times=1,
+ preserve_symlinks=0,
+ update=0,
+ verbose=0,
+ 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)
+
+ outputs = []
+
+ for n in names:
+ src_name = os.path.join(src, n)
+ dst_name = os.path.join(dst, n)
+
+ if preserve_symlinks and os.path.islink(src_name):
+ link_dest = os.readlink(src_name)
+ 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,
+ dry_run=dry_run))
+ else:
+ copy_file(src_name, dst_name, preserve_mode,
+ preserve_times, update, dry_run=dry_run)
+ outputs.append(dst_name)
+
+ return outputs
+
+# copy_tree ()
+
+# Helper for remove_tree()
+def _build_cmdtuple(path, cmdtuples):
+ 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=0, 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
+
+ log.info("removing '%s' (and everything under it)", directory)
+ if dry_run:
+ return
+ cmdtuples = []
+ _build_cmdtuple(directory, cmdtuples)
+ for cmd in cmdtuples:
+ try:
+ apply(cmd[0], (cmd[1],))
+ # remove dir from cache if it's already there
+ abspath = os.path.abspath(cmd[1])
+ if _path_created.has_key(abspath):
+ 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 so
+ it can be the second argument to os.path.join().
+ """
+ drive, path = os.path.splitdrive(path)
+ if sys.platform == 'mac':
+ return os.sep + path
+ else:
+ if path[0:1] == os.sep:
+ path = drive + path[1:]
+ return path
--- /dev/null
+++ b/sys/lib/python/distutils/dist.py
@@ -1,0 +1,1222 @@
+"""distutils.dist
+
+Provides the Distribution class, which represents the module distribution
+being built/installed/distributed.
+"""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: dist.py 38697 2005-03-23 18:54:36Z loewis $"
+
+import sys, os, string, re
+from types import *
+from copy import copy
+
+try:
+ import warnings
+except ImportError:
+ warnings = None
+
+from distutils.errors import *
+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
+
+# 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"),
+ ]
+
+ # '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
+
+ # 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:
+ 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 attrs.has_key('licence'):
+ 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")
+
+ self.finalize_options()
+
+ # __init__ ()
+
+
+ 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:
+ print indent + header
+ indent = indent + " "
+
+ if not commands:
+ print indent + "no commands known yet"
+ return
+
+ for cmd_name in commands:
+ opt_dict = self.command_options.get(cmd_name)
+ if opt_dict is None:
+ print indent + "no option dict for '%s' command" % cmd_name
+ else:
+ print indent + "option dict for '%s' command:" % cmd_name
+ out = pformat(opt_dict)
+ for line in string.split(out, "\n"):
+ print indent + " " + line
+
+ # dump_option_dicts ()
+
+
+
+ # -- 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.
+ """
+ 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 os.environ.has_key('HOME'):
+ user_file = os.path.join(os.environ.get('HOME'), 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)
+
+ return files
+
+ # find_config_files ()
+
+
+ def parse_config_files (self, filenames=None):
+
+ from ConfigParser import ConfigParser
+
+ if filenames is None:
+ filenames = self.find_config_files()
+
+ if DEBUG: print "Distribution.parse_config_files():"
+
+ parser = ConfigParser()
+ for filename in filenames:
+ if DEBUG: print " reading", 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 = string.replace(opt, '-', '_')
+ 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 self.command_options.has_key('global'):
+ 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
+
+ # parse_config_files ()
+
+
+ # -- 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()
+ if sys.platform == 'mac':
+ import EasyDialogs
+ cmdlist = self.get_command_list()
+ self.script_args = EasyDialogs.GetArgv(
+ toplevel_options + self.display_options, cmdlist)
+
+ # 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
+
+ # parse_command_line()
+
+ 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
+ type(cmd_class.user_options) is ListType):
+ 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 = copy(negative_opt)
+ 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
+ type(cmd_class.help_options) is ListType):
+ 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
+ type(cmd_class.help_options) is ListType):
+ 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
+ #print "showing help for option %s of command %s" % \
+ # (help_option[0],cmd_class)
+
+ if callable(func):
+ 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
+
+ # _parse_command_opts ()
+
+ def finalize_options (self):
+ """Set final values for all the options on the Distribution
+ instance, analogous to the .finalize_options() method of Command
+ objects.
+ """
+
+ keywords = self.metadata.keywords
+ if keywords is not None:
+ if type(keywords) is StringType:
+ keywordlist = string.split(keywords, ',')
+ self.metadata.keywords = map(string.strip, keywordlist)
+
+ platforms = self.metadata.platforms
+ if platforms is not None:
+ if type(platforms) is StringType:
+ platformlist = string.split(platforms, ',')
+ self.metadata.platforms = map(string.strip, platformlist)
+
+ 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:")
+
+ if display_options:
+ parser.set_option_table(self.display_options)
+ parser.print_help(
+ "Information display options (just display " +
+ "information, ignore any commands)")
+
+ for command in self.commands:
+ if type(command) is ClassType and issubclass(command, Command):
+ klass = command
+ else:
+ klass = self.get_command_class(command)
+ if (hasattr(klass, 'help_options') and
+ type(klass.help_options) is ListType):
+ 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 gen_usage(self.script_name)
+ return
+
+ # _show_help ()
+
+
+ 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 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 string.join(value, ',')
+ elif opt in ('classifiers', 'provides', 'requires',
+ 'obsoletes'):
+ print string.join(value, '\n')
+ else:
+ print value
+ any_display_options = 1
+
+ return any_display_options
+
+ # handle_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)
+
+ # print_command_list ()
+
+
+ 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:
+ self.print_command_list(extra_commands,
+ "Extra commands",
+ max_length)
+
+ # print_commands ()
+
+ 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, type([])):
+ pkgs = string.split(pkgs or "", ",")
+ for i in range(len(pkgs)):
+ pkgs[i] = string.strip(pkgs[i])
+ pkgs = filter(None, pkgs)
+ 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)
+
+
+ # get_command_class ()
+
+ 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:
+ print "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: print " setting options for '%s' command:" % command_name
+ for (option, (source, value)) in option_dict.items():
+ if DEBUG: print " %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 = type(value) is StringType
+ if neg_opt.has_key(option) 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=1):
+ log.debug(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 Distribution
+
+
+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):
+ 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 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')
+
+ self.write_pkg_file(pkg_info)
+
+ pkg_info.close()
+
+ # write_pkg_info ()
+
+ 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:
+ version = '1.1'
+
+ file.write('Metadata-Version: %s\n' % version)
+ file.write('Name: %s\n' % self.get_name() )
+ file.write('Version: %s\n' % self.get_version() )
+ file.write('Summary: %s\n' % self.get_description() )
+ file.write('Home-page: %s\n' % self.get_url() )
+ file.write('Author: %s\n' % self.get_contact() )
+ file.write('Author-email: %s\n' % self.get_contact_email() )
+ file.write('License: %s\n' % self.get_license() )
+ if self.download_url:
+ file.write('Download-URL: %s\n' % self.download_url)
+
+ long_desc = rfc822_escape( self.get_long_description() )
+ file.write('Description: %s\n' % long_desc)
+
+ keywords = string.join( self.get_keywords(), ',')
+ if keywords:
+ file.write('Keywords: %s\n' % 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_list (self, file, name, values):
+ for value in values:
+ file.write('%s: %s\n' % (name, 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.author or "UNKNOWN"
+
+ def get_author_email(self):
+ return self.author_email or "UNKNOWN"
+
+ def get_maintainer(self):
+ return self.maintainer or "UNKNOWN"
+
+ def get_maintainer_email(self):
+ return self.maintainer_email or "UNKNOWN"
+
+ def get_contact(self):
+ return (self.maintainer or
+ 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.description or "UNKNOWN"
+
+ def get_long_description(self):
+ return 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
+
+# class DistributionMetadata
+
+
+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
+
+
+if __name__ == "__main__":
+ dist = Distribution()
+ print "ok"
--- /dev/null
+++ b/sys/lib/python/distutils/emxccompiler.py
@@ -1,0 +1,315 @@
+"""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: emxccompiler.py 34786 2003-12-02 12:17:59Z aimacintyre $"
+
+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)
+ s = f.read()
+ 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')
+ out_string = out.read()
+ 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)
--- /dev/null
+++ b/sys/lib/python/distutils/errors.py
@@ -1,0 +1,99 @@
+"""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"."""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: errors.py 37828 2004-11-10 22:23:15Z loewis $"
+
+class DistutilsError (Exception):
+ """The root of all Distutils evil."""
+ pass
+
+class DistutilsModuleError (DistutilsError):
+ """Unable to load an expected module, or to find an expected class
+ within some module (in particular, command modules and classes)."""
+ pass
+
+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."""
+ pass
+
+class DistutilsGetoptError (DistutilsError):
+ """The option table provided to 'fancy_getopt()' is bogus."""
+ pass
+
+class DistutilsArgError (DistutilsError):
+ """Raised by fancy_getopt in response to getopt.error -- ie. an
+ error in the command line usage."""
+ pass
+
+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."""
+ pass
+
+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."""
+ pass
+
+class DistutilsSetupError (DistutilsError):
+ """For errors that can be definitely blamed on the setup script,
+ such as invalid keyword arguments to 'setup()'."""
+ pass
+
+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."""
+ pass
+
+class DistutilsExecError (DistutilsError):
+ """Any problems executing an external program (such as the C
+ compiler, when compiling C files)."""
+ pass
+
+class DistutilsInternalError (DistutilsError):
+ """Internal inconsistencies or impossibilities (obviously, this
+ should never be seen if the code is working!)."""
+ pass
+
+class DistutilsTemplateError (DistutilsError):
+ """Syntax error in a file list template."""
+
+
+# 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."""
--- /dev/null
+++ b/sys/lib/python/distutils/extension.py
@@ -1,0 +1,246 @@
+"""distutils.extension
+
+Provides the Extension class, used to describe C/C++ extension
+modules in setup scripts."""
+
+__revision__ = "$Id: extension.py 37623 2004-10-14 10:02:08Z anthonybaxter $"
+
+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)
+ 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 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)
+
+ #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 ()
--- /dev/null
+++ b/sys/lib/python/distutils/fancy_getopt.py
@@ -1,0 +1,502 @@
+"""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
+"""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: fancy_getopt.py 37828 2004-11-10 22:23:15Z loewis $"
+
+import sys, string, re
+from types import *
+import getopt
+from distutils.errors import *
+
+# 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 self.option_index.has_key(long_option):
+ 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 self.option_index.has_key(long_option)
+
+ 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 type(aliases) is DictionaryType
+ for (alias, opt) in aliases.items():
+ if not self.option_index.has_key(alias):
+ raise DistutilsGetoptError, \
+ ("invalid %s '%s': "
+ "option '%s' not defined") % (what, alias, alias)
+ if not self.option_index.has_key(opt):
+ 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 type(long) is not StringType or len(long) < 2:
+ raise DistutilsGetoptError, \
+ ("invalid long option '%s': "
+ "must be a string of length >= 2") % long
+
+ if (not ((short is None) or
+ (type(short) is StringType 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
+
+# wrap_text ()
+
+
+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)
+
+# class OptionDummy
+
+
+if __name__ == "__main__":
+ text = """\
+Tra-la-la, supercalifragilisticexpialidocious.
+How *do* you spell that odd word, anyways?
+(Someone ask Mary -- she'll know [or she'll
+say, "How should I know?"].)"""
+
+ for w in (10, 20, 30, 40):
+ print "width: %d" % w
+ print string.join(wrap_text(text, w), "\n")
--- /dev/null
+++ b/sys/lib/python/distutils/file_util.py
@@ -1,0 +1,253 @@
+"""distutils.file_util
+
+Utility functions for operating on single files.
+"""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: file_util.py 37828 2004-11-10 22:23:15Z loewis $"
+
+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()
+
+# _copy_file_contents()
+
+def copy_file (src, dst,
+ preserve_mode=1,
+ preserve_times=1,
+ update=0,
+ link=None,
+ verbose=0,
+ 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):
+ 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 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)
+
+ # On Mac OS, use the native file copy routine
+ if os.name == 'mac':
+ import macostools
+ try:
+ macostools.copy(src, dst, 0, preserve_times)
+ except os.error, exc:
+ raise DistutilsFileError, \
+ "could not copy '%s' to '%s': %s" % (src, dst, exc[-1])
+
+ # If linking (hard or symbolic), use the appropriate system call
+ # (Unix only, of course, but that's the caller's responsibility)
+ elif 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:
+ os.chmod(dst, S_IMODE(st[ST_MODE]))
+
+ return (dst, 1)
+
+# copy_file ()
+
+
+# XXX I suspect this is Unix-specific -- need porting help!
+def move_file (src, dst,
+ verbose=0,
+ 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
+
+ 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)
+ 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
+
+# move_file ()
+
+
+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")
+ for line in contents:
+ f.write(line + "\n")
+ f.close()
--- /dev/null
+++ b/sys/lib/python/distutils/filelist.py
@@ -1,0 +1,355 @@
+"""distutils.filelist
+
+Provides the FileList class, used for poking about the filesystem
+and building lists of files.
+"""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: filelist.py 37828 2004-11-10 22:23:15Z loewis $"
+
+import os, string, re
+import fnmatch
+from types import *
+from glob import glob
+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(apply(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 = string.split(line)
+ 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)
+
+ # _parse_template_line ()
+
+
+ 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 " + string.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 " + string.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 " + string.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 " + string.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, string.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, string.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
+
+ # process_template_line ()
+
+
+ # -- 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.
+ """
+ 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
+
+ # include_pattern ()
+
+
+ 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
+
+ # exclude_pattern ()
+
+# class FileList
+
+
+# ----------------------------------------------------------------------
+# 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.
+ # XXX currently the "special characters" are just slash -- i.e. this is
+ # Unix-only.
+ pattern_re = re.sub(r'(^|[^\\])\.', r'\1[^/]', pattern_re)
+ return pattern_re
+
+# glob_to_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 type(pattern) is StringType:
+ return re.compile(pattern)
+ else:
+ return pattern
+
+ if pattern:
+ pattern_re = glob_to_re(pattern)
+ else:
+ pattern_re = ''
+
+ if prefix is not None:
+ prefix_re = (glob_to_re(prefix))[0:-1] # ditch trailing $
+ pattern_re = "^" + os.path.join(prefix_re, ".*" + pattern_re)
+ else: # no prefix -- respect anchor flag
+ if anchor:
+ pattern_re = "^" + pattern_re
+
+ return re.compile(pattern_re)
+
+# translate_pattern ()
--- /dev/null
+++ b/sys/lib/python/distutils/log.py
@@ -1,0 +1,69 @@
+"""A simple log mechanism styled after PEP 282."""
+
+# This module should be kept compatible with Python 2.1.
+
+# 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 >= self.threshold:
+ if not args:
+ # msg may contain a '%'. If args is empty,
+ # don't even try to string-format
+ print msg
+ else:
+ print msg % args
+ sys.stdout.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)
--- /dev/null
+++ b/sys/lib/python/distutils/msvccompiler.py
@@ -1,0 +1,652 @@
+"""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)
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: msvccompiler.py 54645 2007-04-01 18:29:47Z neal.norwitz $"
+
+import sys, os, string
+from distutils.errors import \
+ DistutilsExecError, DistutilsPlatformError, \
+ CompileError, LibError, LinkError
+from distutils.ccompiler import \
+ CCompiler, gen_preprocess_options, 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, exc: #
+ 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 os.environ.has_key("DISTUTILS_USE_SDK") and os.environ.has_key("MSSdk") 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, ';')
--- /dev/null
+++ b/sys/lib/python/distutils/mwerkscompiler.py
@@ -1,0 +1,248 @@
+"""distutils.mwerkscompiler
+
+Contains MWerksCompiler, an implementation of the abstract CCompiler class
+for MetroWerks CodeWarrior on the Macintosh. Needs work to support CW on
+Windows."""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: mwerkscompiler.py 37828 2004-11-10 22:23:15Z loewis $"
+
+import sys, os, string
+from types import *
+from distutils.errors import \
+ DistutilsExecError, DistutilsPlatformError, \
+ CompileError, LibError, LinkError
+from distutils.ccompiler import \
+ CCompiler, gen_preprocess_options, gen_lib_options
+import distutils.util
+import distutils.dir_util
+from distutils import log
+import mkcwproject
+
+class MWerksCompiler (CCompiler) :
+ """Concrete class that implements an interface to MetroWerks CodeWarrior,
+ as defined by the CCompiler abstract class."""
+
+ compiler_type = 'mwerks'
+
+ # 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 = ['.r']
+ _exp_extension = '.exp'
+
+ # Needed for the filename generation methods provided by the
+ # base class, CCompiler.
+ src_extensions = (_c_extensions + _cpp_extensions +
+ _rc_extensions)
+ res_extension = '.rsrc'
+ obj_extension = '.obj' # Not used, really
+ static_lib_extension = '.lib'
+ shared_lib_extension = '.slb'
+ static_lib_format = shared_lib_format = '%s%s'
+ exe_extension = ''
+
+
+ def __init__ (self,
+ verbose=0,
+ dry_run=0,
+ force=0):
+
+ CCompiler.__init__ (self, verbose, dry_run, force)
+
+
+ def compile (self,
+ sources,
+ output_dir=None,
+ macros=None,
+ include_dirs=None,
+ debug=0,
+ extra_preargs=None,
+ extra_postargs=None,
+ depends=None):
+ (output_dir, macros, include_dirs) = \
+ self._fix_compile_args (output_dir, macros, include_dirs)
+ self.__sources = sources
+ self.__macros = macros
+ self.__include_dirs = include_dirs
+ # Don't need extra_preargs and extra_postargs for CW
+ return []
+
+ 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):
+ # First fixup.
+ (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)
+
+ # First examine a couple of options for things that aren't implemented yet
+ if not target_desc in (self.SHARED_LIBRARY, self.SHARED_OBJECT):
+ raise DistutilsPlatformError, 'Can only make SHARED_LIBRARY or SHARED_OBJECT targets on the Mac'
+ if runtime_library_dirs:
+ raise DistutilsPlatformError, 'Runtime library dirs not implemented yet'
+ if extra_preargs or extra_postargs:
+ raise DistutilsPlatformError, 'Runtime library dirs not implemented yet'
+ if len(export_symbols) != 1:
+ raise DistutilsPlatformError, 'Need exactly one export symbol'
+ # Next there are various things for which we need absolute pathnames.
+ # This is because we (usually) create the project in a subdirectory of
+ # where we are now, and keeping the paths relative is too much work right
+ # now.
+ sources = map(self._filename_to_abs, self.__sources)
+ include_dirs = map(self._filename_to_abs, self.__include_dirs)
+ if objects:
+ objects = map(self._filename_to_abs, objects)
+ else:
+ objects = []
+ if build_temp:
+ build_temp = self._filename_to_abs(build_temp)
+ else:
+ build_temp = os.curdir()
+ if output_dir:
+ output_filename = os.path.join(output_dir, output_filename)
+ # The output filename needs special handling: splitting it into dir and
+ # filename part. Actually I'm not sure this is really needed, but it
+ # can't hurt.
+ output_filename = self._filename_to_abs(output_filename)
+ output_dir, output_filename = os.path.split(output_filename)
+ # Now we need the short names of a couple of things for putting them
+ # into the project.
+ if output_filename[-8:] == '.ppc.slb':
+ basename = output_filename[:-8]
+ elif output_filename[-11:] == '.carbon.slb':
+ basename = output_filename[:-11]
+ else:
+ basename = os.path.strip(output_filename)[0]
+ projectname = basename + '.mcp'
+ targetname = basename
+ xmlname = basename + '.xml'
+ exportname = basename + '.mcp.exp'
+ prefixname = 'mwerks_%s_config.h'%basename
+ # Create the directories we need
+ distutils.dir_util.mkpath(build_temp, dry_run=self.dry_run)
+ distutils.dir_util.mkpath(output_dir, dry_run=self.dry_run)
+ # And on to filling in the parameters for the project builder
+ settings = {}
+ settings['mac_exportname'] = exportname
+ settings['mac_outputdir'] = output_dir
+ settings['mac_dllname'] = output_filename
+ settings['mac_targetname'] = targetname
+ settings['sysprefix'] = sys.prefix
+ settings['mac_sysprefixtype'] = 'Absolute'
+ sourcefilenames = []
+ sourcefiledirs = []
+ for filename in sources + objects:
+ dirname, filename = os.path.split(filename)
+ sourcefilenames.append(filename)
+ if not dirname in sourcefiledirs:
+ sourcefiledirs.append(dirname)
+ settings['sources'] = sourcefilenames
+ settings['libraries'] = libraries
+ settings['extrasearchdirs'] = sourcefiledirs + include_dirs + library_dirs
+ if self.dry_run:
+ print 'CALLING LINKER IN', os.getcwd()
+ for key, value in settings.items():
+ print '%20.20s %s'%(key, value)
+ return
+ # Build the export file
+ exportfilename = os.path.join(build_temp, exportname)
+ log.debug("\tCreate export file %s", exportfilename)
+ fp = open(exportfilename, 'w')
+ fp.write('%s\n'%export_symbols[0])
+ fp.close()
+ # Generate the prefix file, if needed, and put it in the settings
+ if self.__macros:
+ prefixfilename = os.path.join(os.getcwd(), os.path.join(build_temp, prefixname))
+ fp = open(prefixfilename, 'w')
+ fp.write('#include "mwerks_shcarbon_config.h"\n')
+ for name, value in self.__macros:
+ if value is None:
+ fp.write('#define %s\n'%name)
+ else:
+ fp.write('#define %s %s\n'%(name, value))
+ fp.close()
+ settings['prefixname'] = prefixname
+
+ # Build the XML file. We need the full pathname (only lateron, really)
+ # because we pass this pathname to CodeWarrior in an AppleEvent, and CW
+ # doesn't have a clue about our working directory.
+ xmlfilename = os.path.join(os.getcwd(), os.path.join(build_temp, xmlname))
+ log.debug("\tCreate XML file %s", xmlfilename)
+ xmlbuilder = mkcwproject.cwxmlgen.ProjectBuilder(settings)
+ xmlbuilder.generate()
+ xmldata = settings['tmp_projectxmldata']
+ fp = open(xmlfilename, 'w')
+ fp.write(xmldata)
+ fp.close()
+ # Generate the project. Again a full pathname.
+ projectfilename = os.path.join(os.getcwd(), os.path.join(build_temp, projectname))
+ log.debug('\tCreate project file %s', projectfilename)
+ mkcwproject.makeproject(xmlfilename, projectfilename)
+ # And build it
+ log.debug('\tBuild project')
+ mkcwproject.buildproject(projectfilename)
+
+ def _filename_to_abs(self, filename):
+ # Some filenames seem to be unix-like. Convert to Mac names.
+## if '/' in filename and ':' in filename:
+## raise DistutilsPlatformError, 'Filename may be Unix or Mac style: %s'%filename
+## if '/' in filename:
+## filename = macurl2path(filename)
+ filename = distutils.util.convert_path(filename)
+ if not os.path.isabs(filename):
+ curdir = os.getcwd()
+ filename = os.path.join(curdir, filename)
+ # Finally remove .. components
+ components = string.split(filename, ':')
+ for i in range(1, len(components)):
+ if components[i] == '..':
+ components[i] = ''
+ return string.join(components, ':')
+
+ def library_dir_option (self, dir):
+ """Return the compiler option to add 'dir' to the list of
+ directories searched for libraries.
+ """
+ return # XXXX Not correct...
+
+ def runtime_library_dir_option (self, dir):
+ """Return the compiler option to add 'dir' to the list of
+ directories searched for runtime libraries.
+ """
+ # Nothing needed or Mwerks/Mac.
+ return
+
+ def library_option (self, lib):
+ """Return the compiler option to add 'dir' to the list of libraries
+ linked into the shared library or executable.
+ """
+ return
+
+ 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.
+ """
+ return 0
--- /dev/null
+++ b/sys/lib/python/distutils/spawn.py
@@ -1,0 +1,201 @@
+"""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.
+"""
+
+# This module should be kept compatible with Python 2.1.
+
+__revision__ = "$Id: spawn.py 37828 2004-11-10 22:23:15Z loewis $"
+
+import sys, os, string
+from distutils.errors import *
+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)
+ else:
+ raise DistutilsPlatformError, \
+ "don't know how to spawn programs on platform '%s'" % os.name
+
+# spawn ()
+
+
+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 in range(len(args)):
+ if string.find(args[i], ' ') != -1:
+ args[i] = '"%s"' % args[i]
+ 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(string.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]
+ #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(string.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
+ print "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(string.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:
+ #print "cmd[0] =", cmd[0]
+ #print "cmd =", cmd
+ 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)
+# _spawn_posix ()
+
+
+def find_executable(executable, path=None):
+ """Try 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 = string.split(path, 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
+
+# find_executable()
--- /dev/null
+++ b/sys/lib/python/distutils/sysconfig.py
@@ -1,0 +1,538 @@
+"""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 52234 2006-10-08 17:50:26Z ronald.oussoren $"
+
+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)
+
+# 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.
+
+argv0_path = os.path.dirname(os.path.abspath(sys.executable))
+landmark = os.path.join(argv0_path, "Modules", "Setup")
+
+python_build = os.path.isfile(landmark)
+
+del landmark
+
+
+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:
+ base = os.path.dirname(os.path.abspath(sys.executable))
+ if plat_specific:
+ inc_dir = base
+ else:
+ inc_dir = os.path.join(base, "Include")
+ if not os.path.exists(inc_dir):
+ inc_dir = os.path.join(os.path.dirname(base), "Include")
+ return inc_dir
+# return os.path.join(prefix, "include", "python" + get_python_version())
+ return os.path.join(prefix, "include", "python")
+ 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":
+ 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())
+ libpython = prefix
+ 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":
+ 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 os.environ.has_key('CC'):
+ cc = os.environ['CC']
+ if os.environ.has_key('CXX'):
+ cxx = os.environ['CXX']
+ if os.environ.has_key('LDSHARED'):
+ ldshared = os.environ['LDSHARED']
+ if os.environ.has_key('CPP'):
+ cpp = os.environ['CPP']
+ else:
+ cpp = cc + " -E" # not always
+ if os.environ.has_key('LDFLAGS'):
+ ldshared = ldshared + ' ' + os.environ['LDFLAGS']
+ if os.environ.has_key('CFLAGS'):
+ cflags = opt + ' ' + os.environ['CFLAGS']
+ ldshared = ldshared + ' ' + os.environ['CFLAGS']
+ if os.environ.has_key('CPPFLAGS'):
+ 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:
+ inc_dir = argv0_path
+ 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(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 = string.strip(v)
+ if "$" in v:
+ notdone[n] = v
+ else:
+ try: v = int(v)
+ except ValueError: pass
+ 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 done.has_key(n):
+ item = str(done[n])
+ elif notdone.has_key(n):
+ # get it on a subsequent round
+ found = False
+ elif os.environ.has_key(n):
+ # 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] = string.strip(value)
+ 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()
+ filename = "/sys/src/cmd/python/pyconfig.h"
+ 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 g.has_key('MACOSX_DEPLOYMENT_TARGET'):
+ 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"
+
+ 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 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:
+ 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',
+ # 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
+
+ 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)
--- /dev/null
+++ b/sys/lib/python/distutils/tests/__init__.py
@@ -1,0 +1,35 @@
+"""Test suite for distutils.
+
+This test suite consists of a collection of test modules in the
+distutils.tests package. Each test module has a name starting with
+'test' and contains a function test_suite(). The function is expected
+to return an initialized unittest.TestSuite instance.
+
+Tests for the command classes in the distutils.command package are
+included in distutils.tests as well, instead of using a separate
+distutils.command.tests package, since command identification is done
+by import rather than matching pre-defined names.
+
+"""
+
+import os
+import sys
+import unittest
+
+
+here = os.path.dirname(__file__)
+
+
+def test_suite():
+ suite = unittest.TestSuite()
+ for fn in os.listdir(here):
+ if fn.startswith("test") and fn.endswith(".py"):
+ modname = "distutils.tests." + fn[:-3]
+ __import__(modname)
+ module = sys.modules[modname]
+ suite.addTest(module.test_suite())
+ return suite
+
+
+if __name__ == "__main__":
+ unittest.main(defaultTest="test_suite")
--- /dev/null
+++ b/sys/lib/python/distutils/tests/support.py
@@ -1,0 +1,54 @@
+"""Support code for distutils test cases."""
+
+import shutil
+import tempfile
+
+from distutils import log
+
+
+class LoggingSilencer(object):
+
+ def setUp(self):
+ super(LoggingSilencer, self).setUp()
+ self.threshold = log.set_threshold(log.FATAL)
+
+ def tearDown(self):
+ log.set_threshold(self.threshold)
+ super(LoggingSilencer, self).tearDown()
+
+
+class TempdirManager(object):
+ """Mix-in class that handles temporary directories for test cases.
+
+ This is intended to be used with unittest.TestCase.
+ """
+
+ def setUp(self):
+ super(TempdirManager, self).setUp()
+ self.tempdirs = []
+
+ def tearDown(self):
+ super(TempdirManager, self).tearDown()
+ while self.tempdirs:
+ d = self.tempdirs.pop()
+ shutil.rmtree(d)
+
+ def mkdtemp(self):
+ """Create a temporary directory that will be cleaned up.
+
+ Returns the path of the directory.
+ """
+ d = tempfile.mkdtemp()
+ self.tempdirs.append(d)
+ return d
+
+
+class DummyCommand:
+ """Class to store options for retrieval via set_undefined_options()."""
+
+ def __init__(self, **kwargs):
+ for kw, val in kwargs.items():
+ setattr(self, kw, val)
+
+ def ensure_finalized(self):
+ pass
--- /dev/null
+++ b/sys/lib/python/distutils/tests/test_build_py.py
@@ -1,0 +1,61 @@
+"""Tests for distutils.command.build_py."""
+
+import os
+import unittest
+
+from distutils.command.build_py import build_py
+from distutils.core import Distribution
+
+from distutils.tests import support
+
+
+class BuildPyTestCase(support.TempdirManager,
+ support.LoggingSilencer,
+ unittest.TestCase):
+
+ def test_package_data(self):
+ sources = self.mkdtemp()
+ f = open(os.path.join(sources, "__init__.py"), "w")
+ f.write("# Pretend this is a package.")
+ f.close()
+ f = open(os.path.join(sources, "README.txt"), "w")
+ f.write("Info about this package")
+ f.close()
+
+ destination = self.mkdtemp()
+
+ dist = Distribution({"packages": ["pkg"],
+ "package_dir": {"pkg": sources}})
+ # script_name need not exist, it just need to be initialized
+ dist.script_name = os.path.join(sources, "setup.py")
+ dist.command_obj["build"] = support.DummyCommand(
+ force=0,
+ build_lib=destination)
+ dist.packages = ["pkg"]
+ dist.package_data = {"pkg": ["README.txt"]}
+ dist.package_dir = {"pkg": sources}
+
+ cmd = build_py(dist)
+ cmd.compile = 1
+ cmd.ensure_finalized()
+ self.assertEqual(cmd.package_data, dist.package_data)
+
+ cmd.run()
+
+ # This makes sure the list of outputs includes byte-compiled
+ # files for Python modules but not for package data files
+ # (there shouldn't *be* byte-code files for those!).
+ #
+ self.assertEqual(len(cmd.get_outputs()), 3)
+ pkgdest = os.path.join(destination, "pkg")
+ files = os.listdir(pkgdest)
+ self.assert_("__init__.py" in files)
+ self.assert_("__init__.pyc" in files)
+ self.assert_("README.txt" in files)
+
+
+def test_suite():
+ return unittest.makeSuite(BuildPyTestCase)
+
+if __name__ == "__main__":
+ unittest.main(defaultTest="test_suite")
--- /dev/null
+++ b/sys/lib/python/distutils/tests/test_build_scripts.py
@@ -1,0 +1,81 @@
+"""Tests for distutils.command.build_scripts."""
+
+import os
+import unittest
+
+from distutils.command.build_scripts import build_scripts
+from distutils.core import Distribution
+
+from distutils.tests import support
+
+
+class BuildScriptsTestCase(support.TempdirManager,
+ support.LoggingSilencer,
+ unittest.TestCase):
+
+ def test_default_settings(self):
+ cmd = self.get_build_scripts_cmd("/foo/bar", [])
+ self.assert_(not cmd.force)
+ self.assert_(cmd.build_dir is None)
+
+ cmd.finalize_options()
+
+ self.assert_(cmd.force)
+ self.assertEqual(cmd.build_dir, "/foo/bar")
+
+ def test_build(self):
+ source = self.mkdtemp()
+ target = self.mkdtemp()
+ expected = self.write_sample_scripts(source)
+
+ cmd = self.get_build_scripts_cmd(target,
+ [os.path.join(source, fn)
+ for fn in expected])
+ cmd.finalize_options()
+ cmd.run()
+
+ built = os.listdir(target)
+ for name in expected:
+ self.assert_(name in built)
+
+ def get_build_scripts_cmd(self, target, scripts):
+ import sys
+ dist = Distribution()
+ dist.scripts = scripts
+ dist.command_obj["build"] = support.DummyCommand(
+ build_scripts=target,
+ force=1,
+ executable=sys.executable
+ )
+ return build_scripts(dist)
+
+ def write_sample_scripts(self, dir):
+ expected = []
+ expected.append("script1.py")
+ self.write_script(dir, "script1.py",
+ ("#! /usr/bin/env python2.3\n"
+ "# bogus script w/ Python sh-bang\n"
+ "pass\n"))
+ expected.append("script2.py")
+ self.write_script(dir, "script2.py",
+ ("#!/usr/bin/python\n"
+ "# bogus script w/ Python sh-bang\n"
+ "pass\n"))
+ expected.append("shell.sh")
+ self.write_script(dir, "shell.sh",
+ ("#!/bin/sh\n"
+ "# bogus shell script w/ sh-bang\n"
+ "exit 0\n"))
+ return expected
+
+ def write_script(self, dir, name, text):
+ f = open(os.path.join(dir, name), "w")
+ f.write(text)
+ f.close()
+
+
+def test_suite():
+ return unittest.makeSuite(BuildScriptsTestCase)
+
+if __name__ == "__main__":
+ unittest.main(defaultTest="test_suite")
--- /dev/null
+++ b/sys/lib/python/distutils/tests/test_dist.py
@@ -1,0 +1,189 @@
+"""Tests for distutils.dist."""
+
+import distutils.cmd
+import distutils.dist
+import os
+import shutil
+import StringIO
+import sys
+import tempfile
+import unittest
+
+from test.test_support import TESTFN
+
+
+class test_dist(distutils.cmd.Command):
+ """Sample distutils extension command."""
+
+ user_options = [
+ ("sample-option=", "S", "help text"),
+ ]
+
+ def initialize_options(self):
+ self.sample_option = None
+
+
+class TestDistribution(distutils.dist.Distribution):
+ """Distribution subclasses that avoids the default search for
+ configuration files.
+
+ The ._config_files attribute must be set before
+ .parse_config_files() is called.
+ """
+
+ def find_config_files(self):
+ return self._config_files
+
+
+class DistributionTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.argv = sys.argv[:]
+ del sys.argv[1:]
+
+ def tearDown(self):
+ sys.argv[:] = self.argv
+
+ def create_distribution(self, configfiles=()):
+ d = TestDistribution()
+ d._config_files = configfiles
+ d.parse_config_files()
+ d.parse_command_line()
+ return d
+
+ def test_command_packages_unspecified(self):
+ sys.argv.append("build")
+ d = self.create_distribution()
+ self.assertEqual(d.get_command_packages(), ["distutils.command"])
+
+ def test_command_packages_cmdline(self):
+ sys.argv.extend(["--command-packages",
+ "foo.bar,distutils.tests",
+ "test_dist",
+ "-Ssometext",
+ ])
+ d = self.create_distribution()
+ # let's actually try to load our test command:
+ self.assertEqual(d.get_command_packages(),
+ ["distutils.command", "foo.bar", "distutils.tests"])
+ cmd = d.get_command_obj("test_dist")
+ self.assert_(isinstance(cmd, test_dist))
+ self.assertEqual(cmd.sample_option, "sometext")
+
+ def test_command_packages_configfile(self):
+ sys.argv.append("build")
+ f = open(TESTFN, "w")
+ try:
+ print >>f, "[global]"
+ print >>f, "command_packages = foo.bar, splat"
+ f.close()
+ d = self.create_distribution([TESTFN])
+ self.assertEqual(d.get_command_packages(),
+ ["distutils.command", "foo.bar", "splat"])
+
+ # ensure command line overrides config:
+ sys.argv[1:] = ["--command-packages", "spork", "build"]
+ d = self.create_distribution([TESTFN])
+ self.assertEqual(d.get_command_packages(),
+ ["distutils.command", "spork"])
+
+ # Setting --command-packages to '' should cause the default to
+ # be used even if a config file specified something else:
+ sys.argv[1:] = ["--command-packages", "", "build"]
+ d = self.create_distribution([TESTFN])
+ self.assertEqual(d.get_command_packages(), ["distutils.command"])
+
+ finally:
+ os.unlink(TESTFN)
+
+
+class MetadataTestCase(unittest.TestCase):
+
+ def test_simple_metadata(self):
+ attrs = {"name": "package",
+ "version": "1.0"}
+ dist = distutils.dist.Distribution(attrs)
+ meta = self.format_metadata(dist)
+ self.assert_("Metadata-Version: 1.0" in meta)
+ self.assert_("provides:" not in meta.lower())
+ self.assert_("requires:" not in meta.lower())
+ self.assert_("obsoletes:" not in meta.lower())
+
+ def test_provides(self):
+ attrs = {"name": "package",
+ "version": "1.0",
+ "provides": ["package", "package.sub"]}
+ dist = distutils.dist.Distribution(attrs)
+ self.assertEqual(dist.metadata.get_provides(),
+ ["package", "package.sub"])
+ self.assertEqual(dist.get_provides(),
+ ["package", "package.sub"])
+ meta = self.format_metadata(dist)
+ self.assert_("Metadata-Version: 1.1" in meta)
+ self.assert_("requires:" not in meta.lower())
+ self.assert_("obsoletes:" not in meta.lower())
+
+ def test_provides_illegal(self):
+ self.assertRaises(ValueError,
+ distutils.dist.Distribution,
+ {"name": "package",
+ "version": "1.0",
+ "provides": ["my.pkg (splat)"]})
+
+ def test_requires(self):
+ attrs = {"name": "package",
+ "version": "1.0",
+ "requires": ["other", "another (==1.0)"]}
+ dist = distutils.dist.Distribution(attrs)
+ self.assertEqual(dist.metadata.get_requires(),
+ ["other", "another (==1.0)"])
+ self.assertEqual(dist.get_requires(),
+ ["other", "another (==1.0)"])
+ meta = self.format_metadata(dist)
+ self.assert_("Metadata-Version: 1.1" in meta)
+ self.assert_("provides:" not in meta.lower())
+ self.assert_("Requires: other" in meta)
+ self.assert_("Requires: another (==1.0)" in meta)
+ self.assert_("obsoletes:" not in meta.lower())
+
+ def test_requires_illegal(self):
+ self.assertRaises(ValueError,
+ distutils.dist.Distribution,
+ {"name": "package",
+ "version": "1.0",
+ "requires": ["my.pkg (splat)"]})
+
+ def test_obsoletes(self):
+ attrs = {"name": "package",
+ "version": "1.0",
+ "obsoletes": ["other", "another (<1.0)"]}
+ dist = distutils.dist.Distribution(attrs)
+ self.assertEqual(dist.metadata.get_obsoletes(),
+ ["other", "another (<1.0)"])
+ self.assertEqual(dist.get_obsoletes(),
+ ["other", "another (<1.0)"])
+ meta = self.format_metadata(dist)
+ self.assert_("Metadata-Version: 1.1" in meta)
+ self.assert_("provides:" not in meta.lower())
+ self.assert_("requires:" not in meta.lower())
+ self.assert_("Obsoletes: other" in meta)
+ self.assert_("Obsoletes: another (<1.0)" in meta)
+
+ def test_obsoletes_illegal(self):
+ self.assertRaises(ValueError,
+ distutils.dist.Distribution,
+ {"name": "package",
+ "version": "1.0",
+ "obsoletes": ["my.pkg (splat)"]})
+
+ def format_metadata(self, dist):
+ sio = StringIO.StringIO()
+ dist.metadata.write_pkg_file(sio)
+ return sio.getvalue()
+
+
+def test_suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(DistributionTestCase))
+ suite.addTest(unittest.makeSuite(MetadataTestCase))
+ return suite
--- /dev/null
+++ b/sys/lib/python/distutils/tests/test_install.py
@@ -1,0 +1,55 @@
+"""Tests for distutils.command.install."""
+
+import os
+import unittest
+
+from distutils.command.install import install
+from distutils.core import Distribution
+
+from distutils.tests import support
+
+
+class InstallTestCase(support.TempdirManager, unittest.TestCase):
+
+ def test_home_installation_scheme(self):
+ # This ensure two things:
+ # - that --home generates the desired set of directory names
+ # - test --home is supported on all platforms
+ builddir = self.mkdtemp()
+ destination = os.path.join(builddir, "installation")
+
+ dist = Distribution({"name": "foopkg"})
+ # script_name need not exist, it just need to be initialized
+ dist.script_name = os.path.join(builddir, "setup.py")
+ dist.command_obj["build"] = support.DummyCommand(
+ build_base=builddir,
+ build_lib=os.path.join(builddir, "lib"),
+ )
+
+ cmd = install(dist)
+ cmd.home = destination
+ cmd.ensure_finalized()
+
+ self.assertEqual(cmd.install_base, destination)
+ self.assertEqual(cmd.install_platbase, destination)
+
+ def check_path(got, expected):
+ got = os.path.normpath(got)
+ expected = os.path.normpath(expected)
+ self.assertEqual(got, expected)
+
+ libdir = os.path.join(destination, "lib", "python")
+ check_path(cmd.install_lib, libdir)
+ check_path(cmd.install_platlib, libdir)
+ check_path(cmd.install_purelib, libdir)
+ check_path(cmd.install_headers,
+ os.path.join(destination, "include", "python", "foopkg"))
+ check_path(cmd.install_scripts, os.path.join(destination, "bin"))
+ check_path(cmd.install_data, destination)
+
+
+def test_suite():
+ return unittest.makeSuite(InstallTestCase)
+
+if __name__ == "__main__":
+ unittest.main(defaultTest="test_suite")
--- /dev/null
+++ b/sys/lib/python/distutils/tests/test_install_scripts.py
@@ -1,0 +1,79 @@
+"""Tests for distutils.command.install_scripts."""
+
+import os
+import unittest
+
+from distutils.command.install_scripts import install_scripts
+from distutils.core import Distribution
+
+from distutils.tests import support
+
+
+class InstallScriptsTestCase(support.TempdirManager,
+ support.LoggingSilencer,
+ unittest.TestCase):
+
+ def test_default_settings(self):
+ dist = Distribution()
+ dist.command_obj["build"] = support.DummyCommand(
+ build_scripts="/foo/bar")
+ dist.command_obj["install"] = support.DummyCommand(
+ install_scripts="/splat/funk",
+ force=1,
+ skip_build=1,
+ )
+ cmd = install_scripts(dist)
+ self.assert_(not cmd.force)
+ self.assert_(not cmd.skip_build)
+ self.assert_(cmd.build_dir is None)
+ self.assert_(cmd.install_dir is None)
+
+ cmd.finalize_options()
+
+ self.assert_(cmd.force)
+ self.assert_(cmd.skip_build)
+ self.assertEqual(cmd.build_dir, "/foo/bar")
+ self.assertEqual(cmd.install_dir, "/splat/funk")
+
+ def test_installation(self):
+ source = self.mkdtemp()
+ expected = []
+
+ def write_script(name, text):
+ expected.append(name)
+ f = open(os.path.join(source, name), "w")
+ f.write(text)
+ f.close()
+
+ write_script("script1.py", ("#! /usr/bin/env python2.3\n"
+ "# bogus script w/ Python sh-bang\n"
+ "pass\n"))
+ write_script("script2.py", ("#!/usr/bin/python\n"
+ "# bogus script w/ Python sh-bang\n"
+ "pass\n"))
+ write_script("shell.sh", ("#!/bin/sh\n"
+ "# bogus shell script w/ sh-bang\n"
+ "exit 0\n"))
+
+ target = self.mkdtemp()
+ dist = Distribution()
+ dist.command_obj["build"] = support.DummyCommand(build_scripts=source)
+ dist.command_obj["install"] = support.DummyCommand(
+ install_scripts=target,
+ force=1,
+ skip_build=1,
+ )
+ cmd = install_scripts(dist)
+ cmd.finalize_options()
+ cmd.run()
+
+ installed = os.listdir(target)
+ for name in expected:
+ self.assert_(name in installed)
+
+
+def test_suite():
+ return unittest.makeSuite(InstallScriptsTestCase)
+
+if __name__ == "__main__":
+ unittest.main(defaultTest="test_suite")
--- /dev/null
+++ b/sys/lib/python/distutils/tests/test_versionpredicate.py
@@ -1,0 +1,9 @@
+"""Tests harness for distutils.versionpredicate.
+
+"""
+
+import distutils.versionpredicate
+import doctest
+
+def test_suite():
+ return doctest.DocTestSuite(distutils.versionpredicate)
--- /dev/null
+++ b/sys/lib/python/distutils/text_file.py
@@ -1,0 +1,382 @@
+"""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: text_file.py 29687 2002-11-14 02:25:42Z akuchling $"
+
+from types import *
+import sys, os, string
+
+
+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 options.has_key (opt):
+ setattr (self, opt, options[opt])
+
+ else:
+ setattr (self, opt, self.default_options[opt])
+
+ # sanity check client option hash
+ for opt in options.keys():
+ if not self.default_options.has_key (opt):
+ 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 type (line) in (ListType, TupleType):
+ outmsg.append("lines %d-%d: " % tuple (line))
+ else:
+ outmsg.append("line %d: " % line)
+ outmsg.append(str(msg))
+ return string.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 = string.find (line, "#")
+ 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 string.strip(line) == "":
+ continue
+
+ else: # it's an escaped "#"
+ line = string.replace (line, "\\#", "#")
+
+
+ # 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 = string.lstrip (line)
+ line = buildup_line + line
+
+ # careful: pay attention to line number when incrementing it
+ if type (self.current_line) is ListType:
+ 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 type (self.current_line) is ListType:
+ 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 = string.strip (line)
+ elif self.lstrip_ws:
+ line = string.lstrip (line)
+ elif self.rstrip_ws:
+ line = string.rstrip (line)
+
+ # 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)
+
+
+if __name__ == "__main__":
+ test_data = """# test file
+
+line 3 \\
+# intervening comment
+ continues on next line
+"""
+ # result 1: no fancy options
+ result1 = map (lambda x: x + "\n", string.split (test_data, "\n")[0:-1])
+
+ # result 2: just strip comments
+ result2 = ["\n",
+ "line 3 \\\n",
+ " continues on next line\n"]
+
+ # result 3: just strip blank lines
+ result3 = ["# test file\n",
+ "line 3 \\\n",
+ "# intervening comment\n",
+ " continues on next line\n"]
+
+ # result 4: default, strip comments, blank lines, and trailing whitespace
+ result4 = ["line 3 \\",
+ " continues on next line"]
+
+ # result 5: strip comments and blanks, plus join lines (but don't
+ # "collapse" joined lines
+ result5 = ["line 3 continues on next line"]
+
+ # result 6: strip comments and blanks, plus join lines (and
+ # "collapse" joined lines
+ result6 = ["line 3 continues on next line"]
+
+ def test_input (count, description, file, expected_result):
+ result = file.readlines ()
+ # result = string.join (result, '')
+ if result == expected_result:
+ print "ok %d (%s)" % (count, description)
+ else:
+ print "not ok %d (%s):" % (count, description)
+ print "** expected:"
+ print expected_result
+ print "** received:"
+ print result
+
+
+ filename = "test.txt"
+ out_file = open (filename, "w")
+ out_file.write (test_data)
+ out_file.close ()
+
+ in_file = TextFile (filename, strip_comments=0, skip_blanks=0,
+ lstrip_ws=0, rstrip_ws=0)
+ test_input (1, "no processing", in_file, result1)
+
+ in_file = TextFile (filename, strip_comments=1, skip_blanks=0,
+ lstrip_ws=0, rstrip_ws=0)
+ test_input (2, "strip comments", in_file, result2)
+
+ in_file = TextFile (filename, strip_comments=0, skip_blanks=1,
+ lstrip_ws=0, rstrip_ws=0)
+ test_input (3, "strip blanks", in_file, result3)
+
+ in_file = TextFile (filename)
+ test_input (4, "default processing", in_file, result4)
+
+ in_file = TextFile (filename, strip_comments=1, skip_blanks=1,
+ join_lines=1, rstrip_ws=1)
+ test_input (5, "join lines without collapsing", in_file, result5)
+
+ in_file = TextFile (filename, strip_comments=1, skip_blanks=1,
+ join_lines=1, rstrip_ws=1, collapse_join=1)
+ test_input (6, "join lines with collapsing", in_file, result6)
+
+ os.remove (filename)
--- /dev/null
+++ b/sys/lib/python/distutils/unixccompiler.py
@@ -1,0 +1,315 @@
+"""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: unixccompiler.py 52237 2006-10-08 17:52:37Z ronald.oussoren $"
+
+import os, sys
+from types import StringType, NoneType
+from copy import copy
+
+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
+
+# 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.
+
+def _darwin_compiler_fixup(compiler_so, cc_args):
+ """
+ This function will strip '-isysroot PATH' and '-arch ARCH' from the
+ compile flags if the user has specified one them in extra_compile_flags.
+
+ This is needed because '-arch ARCH' adds another architecture to the
+ build, without a way to remove an architecture. Furthermore GCC will
+ barf if multiple '-isysroot' arguments are present.
+ """
+ stripArch = stripSysroot = 0
+
+ compiler_so = list(compiler_so)
+ kernel_version = os.uname()[2] # 8.4.3
+ major_version = int(kernel_version.split('.')[0])
+
+ if major_version < 8:
+ # OSX before 10.4.0, these don't support -arch and -isysroot at
+ # all.
+ stripArch = stripSysroot = True
+ else:
+ stripArch = '-arch' in cc_args
+ stripSysroot = '-isysroot' in cc_args
+
+ if stripArch:
+ while 1:
+ try:
+ index = compiler_so.index('-arch')
+ # Strip this argument and the next one:
+ del compiler_so[index:index+2]
+ except ValueError:
+ break
+
+ if stripSysroot:
+ try:
+ index = compiler_so.index('-isysroot')
+ # Strip this argument and the next one:
+ del compiler_so[index:index+2]
+ except ValueError:
+ pass
+
+ # Check if the SDK that is used during compilation actually exists,
+ # the universal build requires the usage of a universal SDK and not all
+ # users have that installed by default.
+ sysroot = None
+ if '-isysroot' in cc_args:
+ idx = cc_args.index('-isysroot')
+ sysroot = cc_args[idx+1]
+ elif '-isysroot' in compiler_so:
+ idx = compiler_so.index('-isysroot')
+ sysroot = compiler_so[idx+1]
+
+ if sysroot and not os.path.isdir(sysroot):
+ log.warn("Compiling with an SDK that doesn't seem to exist: %s",
+ sysroot)
+ log.warn("Please check your Xcode installation")
+
+ return compiler_so
+
+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 = _darwin_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 = _darwin_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 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":
+ return "+s -L" + dir
+ elif sys.platform[:7] == "irix646" or sys.platform[:6] == "osf1V5":
+ return ["-rpath", dir]
+ elif compiler[:3] == "gcc" or compiler[:3] == "g++":
+ 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')
+
+ 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)
+ # 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
--- /dev/null
+++ b/sys/lib/python/distutils/util.py
@@ -1,0 +1,513 @@
+"""distutils.util
+
+Miscellaneous utility functions -- anything that doesn't fit into
+one of the other *util.py modules.
+"""
+
+__revision__ = "$Id: util.py 46157 2006-05-23 21:54:23Z tim.peters $"
+
+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
+
+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
+
+ For non-POSIX platforms, currently just returns '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 not 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:
+ macver = '.'.join(m.group(1).split('.')[:2])
+ # else: fall back to the default behaviour
+
+ if macver:
+ from distutils.sysconfig import get_config_vars
+ release = macver
+ osname = "macosx"
+
+
+ if (release + '.') < '10.4.' and \
+ get_config_vars().get('UNIVERSALSDK', '').strip():
+ # The universal build will build fat binaries, but not on
+ # systems before 10.4
+ machine = 'fat'
+
+ elif machine in ('PowerPC', 'Power_Macintosh'):
+ # Pick a sane name for the PPC architecture.
+ machine = 'ppc'
+
+ 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 apply(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.
+ """
+ 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 not os.environ.has_key('HOME'):
+ import pwd
+ os.environ['HOME'] = pwd.getpwuid(os.getuid())[5]
+
+ if not os.environ.has_key('PLAT'):
+ 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 local_vars.has_key(var_name):
+ 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:
+ apply(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.
+ """
+
+ # 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)
+ 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')
+ lines = map(string.strip, lines)
+ header = string.join(lines, '\n' + 8*' ')
+ return header
--- /dev/null
+++ b/sys/lib/python/distutils/version.py
@@ -1,0 +1,299 @@
+#
+# distutils/version.py
+#
+# Implements multiple version numbering conventions for the
+# Python Module Distribution Utilities.
+#
+# $Id: version.py 29687 2002-11-14 02:25:42Z akuchling $
+#
+
+"""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 separate 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
--- /dev/null
+++ b/sys/lib/python/distutils/versionpredicate.py
@@ -1,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
--- /dev/null
+++ b/sys/lib/python/doctest.py
@@ -1,0 +1,2637 @@
+# 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
+
+# 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'):
+ return package.__loader__.get_data(filename), filename
+ return open(filename).read(), filename
+
+def _indent(s, indent=4):
+ """
+ Add the given number of space characters to the beginning every
+ non-blank line in `s`, and return the result.
+ """
+ # 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
+
+# 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
+ pdb.Pdb.__init__(self, stdout=out)
+
+ 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
+
+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))
+
+
+ # 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)
+ 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)
+
+ # 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.isfunction(object):
+ return module.__dict__ is object.func_globals
+ elif inspect.isclass(object):
+ return module.__name__ == object.__module__
+ elif inspect.getmodule(object) is not None:
+ return module is inspect.getmodule(object)
+ 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]
+ 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 -> (0, 2)
+ _TestClass.__init__ -> (0, 2)
+ _TestClass.get -> (0, 2)
+ _TestClass.square -> (0, 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.
+ (0, 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 supress
+ # 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(0), m2.group(0),
+ 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 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>[\w\.]+)'
+ 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'))]
+ return example.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
+
+ try:
+ return self.__run(test, compileflags, out)
+ finally:
+ sys.stdout = save_stdout
+ pdb.set_trace = save_set_trace
+ linecache.getlines = self.save_linecache_getlines
+ 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 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:
+ 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:
+
+ >>> 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)>
+
+ >>> 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)
+ (0, 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 doctest.__doc__ 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 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 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 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 (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 (f,t)
+
+ def rundict(self, d, name, module=None):
+ import new
+ m = new.module(name)
+ m.__dict__.update(d)
+ if module is None:
+ module = False
+ return self.rundoc(m, name, module)
+
+ def run__test__(self, d, name):
+ import new
+ m = new.module(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 unexepcted
+ 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)
+ self.tearDown()
+
+ def id(self):
+ return self._dt_test.name
+
+ 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
+
+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 globs is None:
+ globs = module.__dict__
+ if not tests:
+ # Why do we want to do this? Because it reveals a bug that might
+ # otherwise be hidden.
+ raise ValueError(module, "has no tests")
+
+ 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]
+ 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():
+ r = unittest.TextTestRunner()
+ r.run(DocTestSuite())
+
+if __name__ == "__main__":
+ _test()
--- /dev/null
+++ b/sys/lib/python/dumbdbm.py
@@ -1,0 +1,233 @@
+"""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._mode)
+ 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._mode)
+ 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._mode)
+ 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 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
+ return _Database(file, mode)
--- /dev/null
+++ b/sys/lib/python/dummy_thread.py
@@ -1,0 +1,152 @@
+"""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
+
+"""
+__author__ = "Brett Cannon"
+__email__ = "brett@python.org"
+
+# 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
+import warnings
+
+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:
+ self.locked_status = True
+ return None
+ elif not waitflag:
+ if not self.locked_status:
+ self.locked_status = True
+ return True
+ else:
+ return False
+ else:
+ self.locked_status = True
+ return True
+
+ __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
--- /dev/null
+++ b/sys/lib/python/dummy_threading.py
@@ -1,0 +1,83 @@
+"""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.
+
+:Author: Brett Cannon
+:Contact: brett@python.org
+
+XXX: Try to get rid of ``_dummy_threading``.
+
+"""
+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
--- /dev/null
+++ b/sys/lib/python/email/__init__.py
@@ -1,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.1'
+
+__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)
--- /dev/null
+++ b/sys/lib/python/email/_parseaddr.py
@@ -1,0 +1,480 @@
+# 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
+
+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
+ tzoffset = None
+ tz = tz.upper()
+ if _timezones.has_key(tz):
+ 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 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 quote(str):
+ """Add quotes around a string."""
+ 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"' % 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]
--- /dev/null
+++ b/sys/lib/python/email/base64mime.py
@@ -1,0 +1,184 @@
+# 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',
+ ]
+
+import re
+
+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
--- /dev/null
+++ b/sys/lib/python/email/charset.py
@@ -1,0 +1,388 @@
+# 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 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),
+ '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',
+ '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()
+ # Set the input charset after filtering through the aliases
+ 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
--- /dev/null
+++ b/sys/lib/python/email/encoders.py
@@ -1,0 +1,88 @@
+# 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:
+ # iso-2022-* is non-ASCII but still 7-bit
+ charset = msg.get_charset()
+ output_cset = charset and charset.output_charset
+ if output_cset and output_cset.lower().startswith('iso-2202-'):
+ msg['Content-Transfer-Encoding'] = '7bit'
+ else:
+ msg['Content-Transfer-Encoding'] = '8bit'
+ else:
+ msg['Content-Transfer-Encoding'] = '7bit'
+
+
+
+def encode_noop(msg):
+ """Do nothing."""
--- /dev/null
+++ b/sys/lib/python/email/errors.py
@@ -1,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."""
--- /dev/null
+++ b/sys/lib/python/email/feedparser.py
@@ -1,0 +1,480 @@
+# 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 throw 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)$')
+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()
+ # 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 throw 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')
--- /dev/null
+++ b/sys/lib/python/email/generator.py
@@ -1,0 +1,348 @@
+# Copyright (C) 2001-2006 Python Software Foundation
+# Author: Barry Warsaw
+# 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.
+ print >> self._fp, Header(
+ v, maxlinelen=self._maxheaderlen,
+ header_name=h, continuation_ws='\t').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())
+ # Now make sure the boundary we've selected doesn't appear in any of
+ # the message texts.
+ alltext = NL.join(msgtexts)
+ # BAW: What about boundaries that are wrapped in double-quotes?
+ boundary = msg.get_boundary(failobj=_make_boundary(alltext))
+ # If we had to calculate a new boundary because the body text
+ # contained that string, set the new boundary. We don't do it
+ # unconditionally because, while set_boundary() preserves order, it
+ # doesn't preserve newlines/continuations in headers. This is no big
+ # deal in practice, but turns out to be inconvenient for the unittest
+ # suite.
+ if msg.get_boundary() <> boundary:
+ msg.set_boundary(boundary)
+ # If there's a preamble, write it out, with a trailing CRLF
+ if msg.preamble is not None:
+ print >> self._fp, msg.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
+ self._fp.write(msg.epilogue)
+
+ 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.
+ g.flatten(msg.get_payload(0), unixfrom=False)
+ self._fp.write(s.getvalue())
+
+
+
+_FMT = '[Non-text (%(type)s) part of message omitted, filename %(filename)s]'
+
+class DecodedGenerator(Generator):
+ """Generator 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
--- /dev/null
+++ b/sys/lib/python/email/header.py
@@ -1,0 +1,503 @@
+# 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]+:$')
+
+
+
+# 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':
+ 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)
+ return self._encode_chunks(newchunks, maxlinelen)
+
+
+
+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
--- /dev/null
+++ b/sys/lib/python/email/iterators.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/email/message.py
@@ -1,0 +1,786 @@
+# 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 used to 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.
+paramre = re.compile(r'\s*;\s*')
+# Regular expression that matches `special' characters in parameters, the
+# existance of which force quoting of the parameter value.
+tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]')
+
+
+
+# Helper functions
+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 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) % 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 occurrance 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 not self.has_key('MIME-Version'):
+ self.add_header('MIME-Version', '1.0')
+ if not self.has_key('Content-Type'):
+ self.add_header('Content-Type', 'text/plain',
+ charset=charset.get_output_charset())
+ else:
+ self.set_param('charset', charset.get_output_charset())
+ if str(charset) <> charset.get_output_charset():
+ self._payload = charset.body_encode(self._payload)
+ if not self.has_key('Content-Transfer-Encoding'):
+ 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
+ occurrance 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.
+
+ 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 = paramre.split(value)[0].lower().strip()
+ # 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 not self.has_key(header):
+ 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 not self.has_key(header) 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 not self.has_key(header):
+ 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 not self.has_key(header):
+ 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-disposition')
+ 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
--- /dev/null
+++ b/sys/lib/python/email/mime/application.py
@@ -1,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 applicatoin 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)
--- /dev/null
+++ b/sys/lib/python/email/mime/audio.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/email/mime/base.py
@@ -1,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'
--- /dev/null
+++ b/sys/lib/python/email/mime/image.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/email/mime/message.py
@@ -1,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')
--- /dev/null
+++ b/sys/lib/python/email/mime/multipart.py
@@ -1,0 +1,41 @@
+# 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)
+ if _subparts:
+ for p in _subparts:
+ self.attach(p)
+ if boundary:
+ self.set_boundary(boundary)
--- /dev/null
+++ b/sys/lib/python/email/mime/nonmultipart.py
@@ -1,0 +1,26 @@
+# 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."""
+
+ __pychecker__ = 'unusednames=payload'
+
+ 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/*')
+
+ del __pychecker__
--- /dev/null
+++ b/sys/lib/python/email/mime/text.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/email/parser.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/email/quoprimime.py
@@ -1,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'=\w{2}', _unquote_match, s)
--- /dev/null
+++ b/sys/lib/python/email/utils.py
@@ -1,0 +1,323 @@
+# Copyright (C) 2001-2006 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',
+ 'parseaddr',
+ 'parsedate',
+ 'parsedate_tz',
+ 'unquote',
+ ]
+
+import os
+import re
+import time
+import base64
+import random
+import socket
+import urllib
+import warnings
+from cStringIO import StringIO
+
+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):
+ # We can't quite use base64.encodestring() since it tacks on a "courtesy
+ # newline". Blech!
+ if not s:
+ return s
+ value = base64.decodestring(s)
+ if not s.endswith('\n') and value.endswith('\n'):
+ return value[:-1]
+ return value
+
+
+
+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)
--- /dev/null
+++ b/sys/lib/python/encodings/__init__.py
@@ -1,0 +1,154 @@
+""" 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, types
+from encodings import aliases
+
+_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 type(encoding) is types.UnicodeType:
+ # 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:
+ mod = __import__('encodings.' + modname,
+ globals(), locals(), _import_tail)
+ 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 callable(entry[0]) or \
+ not callable(entry[1]) or \
+ (entry[2] is not None and not callable(entry[2])) or \
+ (entry[3] is not None and not callable(entry[3])) or \
+ (len(entry) > 4 and entry[4] is not None and not callable(entry[4])) or \
+ (len(entry) > 5 and entry[5] is not None and not callable(entry[5])):
+ 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 not _aliases.has_key(alias):
+ _aliases[alias] = modname
+
+ # Return the registry entry
+ return entry
+
+# Register the search_function in the Python codec registry
+codecs.register(search_function)
--- /dev/null
+++ b/sys/lib/python/encodings/aliases.py
@@ -1,0 +1,508 @@
+""" 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',
+
+ # 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',
+
+ # 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',
+
+ # 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_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',
+
+}
--- /dev/null
+++ b/sys/lib/python/encodings/ascii.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/base64_codec.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/big5.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/big5hkscs.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/bz2_codec.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/charmap.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/cp037.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/cp1006.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/cp1026.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/cp1140.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/cp1250.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/cp1251.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/cp1252.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/cp1253.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/cp1254.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/cp1255.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/cp1256.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/cp1257.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/cp1258.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/cp424.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/cp437.py
@@ -1,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
+}
--- /dev/null
+++ b/sys/lib/python/encodings/cp500.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/cp737.py
@@ -1,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
+}
--- /dev/null
+++ b/sys/lib/python/encodings/cp775.py
@@ -1,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
+}
--- /dev/null
+++ b/sys/lib/python/encodings/cp850.py
@@ -1,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
+}
--- /dev/null
+++ b/sys/lib/python/encodings/cp852.py
@@ -1,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
+}
--- /dev/null
+++ b/sys/lib/python/encodings/cp855.py
@@ -1,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
+}
--- /dev/null
+++ b/sys/lib/python/encodings/cp856.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/cp857.py
@@ -1,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
+}
--- /dev/null
+++ b/sys/lib/python/encodings/cp860.py
@@ -1,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
+}
--- /dev/null
+++ b/sys/lib/python/encodings/cp861.py
@@ -1,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
+}
--- /dev/null
+++ b/sys/lib/python/encodings/cp862.py
@@ -1,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
+}
--- /dev/null
+++ b/sys/lib/python/encodings/cp863.py
@@ -1,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
+}
--- /dev/null
+++ b/sys/lib/python/encodings/cp864.py
@@ -1,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
+}
--- /dev/null
+++ b/sys/lib/python/encodings/cp865.py
@@ -1,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
+}
--- /dev/null
+++ b/sys/lib/python/encodings/cp866.py
@@ -1,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
+}
--- /dev/null
+++ b/sys/lib/python/encodings/cp869.py
@@ -1,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
+}
--- /dev/null
+++ b/sys/lib/python/encodings/cp874.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/cp875.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/cp932.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/cp949.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/cp950.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/euc_jis_2004.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/euc_jisx0213.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/euc_jp.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/euc_kr.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/gb18030.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/gb2312.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/gbk.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/hex_codec.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/hp_roman8.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/hz.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/idna.py
@@ -1,0 +1,288 @@
+# This module implements the RFCs 3490 (IDNA) and 3491 (Nameprep)
+
+import stringprep, re, codecs
+from unicodedata import ucd_3_2_0 as unicodedata
+
+# IDNA section 3.1
+dots = re.compile(u"[\u002E\u3002\uFF0E\uFF61]")
+
+# IDNA section 5
+ace_prefix = "xn--"
+uace_prefix = unicode(ace_prefix, "ascii")
+
+# This assumes query strings, so AllowUnassigned is true
+def nameprep(label):
+ # Map
+ newlabel = []
+ for c in label:
+ if stringprep.in_table_b1(c):
+ # Map to nothing
+ continue
+ newlabel.append(stringprep.map_table_b2(c))
+ label = u"".join(newlabel)
+
+ # Normalize
+ label = unicodedata.normalize("NFKC", label)
+
+ # Prohibit
+ for c in label:
+ if stringprep.in_table_c12(c) or \
+ stringprep.in_table_c22(c) or \
+ stringprep.in_table_c3(c) or \
+ stringprep.in_table_c4(c) or \
+ stringprep.in_table_c5(c) or \
+ stringprep.in_table_c6(c) or \
+ stringprep.in_table_c7(c) or \
+ stringprep.in_table_c8(c) or \
+ stringprep.in_table_c9(c):
+ raise UnicodeError("Invalid character %r" % c)
+
+ # Check bidi
+ RandAL = map(stringprep.in_table_d1, label)
+ for c in RandAL:
+ if c:
+ # There is a RandAL char in the string. Must perform further
+ # tests:
+ # 1) The characters in section 5.8 MUST be prohibited.
+ # This is table C.8, which was already checked
+ # 2) If a string contains any RandALCat character, the string
+ # MUST NOT contain any LCat character.
+ if filter(stringprep.in_table_d2, label):
+ raise UnicodeError("Violation of BIDI requirement 2")
+
+ # 3) If a string contains any RandALCat character, a
+ # RandALCat character MUST be the first character of the
+ # string, and a RandALCat character MUST be the last
+ # character of the string.
+ if not RandAL[0] or not RandAL[-1]:
+ raise UnicodeError("Violation of BIDI requirement 3")
+
+ return label
+
+def ToASCII(label):
+ try:
+ # Step 1: try ASCII
+ label = label.encode("ascii")
+ except UnicodeError:
+ pass
+ else:
+ # Skip to step 3: UseSTD3ASCIIRules is false, so
+ # Skip to step 8.
+ if 0 < len(label) < 64:
+ return label
+ raise UnicodeError("label empty or too long")
+
+ # Step 2: nameprep
+ label = nameprep(label)
+
+ # Step 3: UseSTD3ASCIIRules is false
+ # Step 4: try ASCII
+ try:
+ label = label.encode("ascii")
+ except UnicodeError:
+ pass
+ else:
+ # Skip to step 8.
+ if 0 < len(label) < 64:
+ return label
+ raise UnicodeError("label empty or too long")
+
+ # Step 5: Check ACE prefix
+ if label.startswith(uace_prefix):
+ raise UnicodeError("Label starts with ACE prefix")
+
+ # Step 6: Encode with PUNYCODE
+ label = label.encode("punycode")
+
+ # Step 7: Prepend ACE prefix
+ label = ace_prefix + label
+
+ # Step 8: Check size
+ if 0 < len(label) < 64:
+ return label
+ raise UnicodeError("label empty or too long")
+
+def ToUnicode(label):
+ # Step 1: Check for ASCII
+ if isinstance(label, str):
+ pure_ascii = True
+ else:
+ try:
+ label = label.encode("ascii")
+ pure_ascii = True
+ except UnicodeError:
+ pure_ascii = False
+ if not pure_ascii:
+ # Step 2: Perform nameprep
+ label = nameprep(label)
+ # It doesn't say this, but apparently, it should be ASCII now
+ try:
+ label = label.encode("ascii")
+ except UnicodeError:
+ raise UnicodeError("Invalid character in IDN label")
+ # Step 3: Check for ACE prefix
+ if not label.startswith(ace_prefix):
+ return unicode(label, "ascii")
+
+ # Step 4: Remove ACE prefix
+ label1 = label[len(ace_prefix):]
+
+ # Step 5: Decode using PUNYCODE
+ result = label1.decode("punycode")
+
+ # Step 6: Apply ToASCII
+ label2 = ToASCII(result)
+
+ # Step 7: Compare the result of step 6 with the one of step 3
+ # label2 will already be in lower case.
+ if label.lower() != label2:
+ raise UnicodeError("IDNA does not round-trip", label, label2)
+
+ # Step 8: return the result of step 5
+ return result
+
+### 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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/iso2022_jp.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/iso2022_jp_1.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/iso2022_jp_2.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/iso2022_jp_2004.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/iso2022_jp_3.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/iso2022_jp_ext.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/iso2022_kr.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/iso8859_1.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/iso8859_10.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/iso8859_11.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/iso8859_13.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/iso8859_14.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/iso8859_15.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/iso8859_16.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/iso8859_2.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/iso8859_3.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/iso8859_4.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/iso8859_5.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/iso8859_6.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/iso8859_7.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/iso8859_8.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/iso8859_9.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/johab.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/koi8_r.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/koi8_u.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/latin_1.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/mac_arabic.py
@@ -1,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
+}
--- /dev/null
+++ b/sys/lib/python/encodings/mac_centeuro.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/mac_croatian.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/mac_cyrillic.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/mac_farsi.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/mac_greek.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/mac_iceland.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/mac_latin2.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/mac_roman.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/mac_romanian.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/mac_turkish.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/mbcs.py
@@ -1,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,
+ )
--- /dev/null
+++ b/sys/lib/python/encodings/palmos.py
@@ -1,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)
--- /dev/null
+++ b/sys/lib/python/encodings/ptcp154.py
@@ -1,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