summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python/src/Lib/wsgiref
diff options
context:
space:
mode:
authorthegeorg <[email protected]>2024-03-15 23:28:02 +0300
committerthegeorg <[email protected]>2024-03-15 23:38:24 +0300
commit6635e51dd2fc4c8fbc3e510cd31c9c9102b7cfda (patch)
treed51d048d3eb5d7a24ec6e4302b589513a3b97de3 /contrib/tools/python/src/Lib/wsgiref
parente894914751eea93bb23102a533c8d481b80c2560 (diff)
Store generated list of frozen modules for contrib/tools/python
a94357bf8071b16879eeabac1f52f54e278c03ed
Diffstat (limited to 'contrib/tools/python/src/Lib/wsgiref')
-rw-r--r--contrib/tools/python/src/Lib/wsgiref/__init__.py23
-rw-r--r--contrib/tools/python/src/Lib/wsgiref/handlers.py450
-rw-r--r--contrib/tools/python/src/Lib/wsgiref/headers.py169
-rw-r--r--contrib/tools/python/src/Lib/wsgiref/simple_server.py163
-rw-r--r--contrib/tools/python/src/Lib/wsgiref/util.py165
-rw-r--r--contrib/tools/python/src/Lib/wsgiref/validate.py432
6 files changed, 0 insertions, 1402 deletions
diff --git a/contrib/tools/python/src/Lib/wsgiref/__init__.py b/contrib/tools/python/src/Lib/wsgiref/__init__.py
deleted file mode 100644
index 46c579f8ece..00000000000
--- a/contrib/tools/python/src/Lib/wsgiref/__init__.py
+++ /dev/null
@@ -1,23 +0,0 @@
-"""wsgiref -- a WSGI (PEP 333) Reference Library
-
-Current Contents:
-
-* util -- Miscellaneous useful functions and wrappers
-
-* headers -- Manage response headers
-
-* handlers -- base classes for server/gateway implementations
-
-* simple_server -- a simple BaseHTTPServer that supports WSGI
-
-* validate -- validation wrapper that sits between an app and a server
- to detect errors in either
-
-To-Do:
-
-* cgi_gateway -- Run WSGI apps under CGI (pending a deployment standard)
-
-* cgi_wrapper -- Run CGI apps under WSGI
-
-* router -- a simple middleware component that handles URL traversal
-"""
diff --git a/contrib/tools/python/src/Lib/wsgiref/handlers.py b/contrib/tools/python/src/Lib/wsgiref/handlers.py
deleted file mode 100644
index 8cb57e223aa..00000000000
--- a/contrib/tools/python/src/Lib/wsgiref/handlers.py
+++ /dev/null
@@ -1,450 +0,0 @@
-"""Base classes for server/gateway implementations"""
-
-from types import StringType
-from util import FileWrapper, guess_scheme, is_hop_by_hop
-from headers import Headers
-
-import sys, os, time
-
-__all__ = ['BaseHandler', 'SimpleHandler', 'BaseCGIHandler', 'CGIHandler']
-
-try:
- dict
-except NameError:
- def dict(items):
- d = {}
- for k,v in items:
- d[k] = v
- return d
-
-# Uncomment for 2.2 compatibility.
-#try:
-# True
-# False
-#except NameError:
-# True = not None
-# False = not True
-
-
-# Weekday and month names for HTTP date/time formatting; always English!
-_weekdayname = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
-_monthname = [None, # Dummy so we can use 1-based month numbers
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
-
-def format_date_time(timestamp):
- year, month, day, hh, mm, ss, wd, y, z = time.gmtime(timestamp)
- return "%s, %02d %3s %4d %02d:%02d:%02d GMT" % (
- _weekdayname[wd], day, _monthname[month], year, hh, mm, ss
- )
-
-
-class BaseHandler:
- """Manage the invocation of a WSGI application"""
-
- # Configuration parameters; can override per-subclass or per-instance
- wsgi_version = (1,0)
- wsgi_multithread = True
- wsgi_multiprocess = True
- wsgi_run_once = False
-
- origin_server = True # We are transmitting direct to client
- http_version = "1.0" # Version that should be used for response
- server_software = None # String name of server software, if any
-
- # os_environ is used to supply configuration from the OS environment:
- # by default it's a copy of 'os.environ' as of import time, but you can
- # override this in e.g. your __init__ method.
- os_environ = dict(os.environ.items())
-
- # Collaborator classes
- wsgi_file_wrapper = FileWrapper # set to None to disable
- headers_class = Headers # must be a Headers-like class
-
- # Error handling (also per-subclass or per-instance)
- traceback_limit = None # Print entire traceback to self.get_stderr()
- error_status = "500 Internal Server Error"
- error_headers = [('Content-Type','text/plain')]
- error_body = "A server error occurred. Please contact the administrator."
-
- # State variables (don't mess with these)
- status = result = None
- headers_sent = False
- headers = None
- bytes_sent = 0
-
- def run(self, application):
- """Invoke the application"""
- # Note to self: don't move the close()! Asynchronous servers shouldn't
- # call close() from finish_response(), so if you close() anywhere but
- # the double-error branch here, you'll break asynchronous servers by
- # prematurely closing. Async servers must return from 'run()' without
- # closing if there might still be output to iterate over.
- try:
- self.setup_environ()
- self.result = application(self.environ, self.start_response)
- self.finish_response()
- except:
- try:
- self.handle_error()
- except:
- # If we get an error handling an error, just give up already!
- self.close()
- raise # ...and let the actual server figure it out.
-
-
- def setup_environ(self):
- """Set up the environment for one request"""
-
- env = self.environ = self.os_environ.copy()
- self.add_cgi_vars()
-
- env['wsgi.input'] = self.get_stdin()
- env['wsgi.errors'] = self.get_stderr()
- env['wsgi.version'] = self.wsgi_version
- env['wsgi.run_once'] = self.wsgi_run_once
- env['wsgi.url_scheme'] = self.get_scheme()
- env['wsgi.multithread'] = self.wsgi_multithread
- env['wsgi.multiprocess'] = self.wsgi_multiprocess
-
- if self.wsgi_file_wrapper is not None:
- env['wsgi.file_wrapper'] = self.wsgi_file_wrapper
-
- if self.origin_server and self.server_software:
- env.setdefault('SERVER_SOFTWARE',self.server_software)
-
-
- def finish_response(self):
- """Send any iterable data, then close self and the iterable
-
- Subclasses intended for use in asynchronous servers will
- want to redefine this method, such that it sets up callbacks
- in the event loop to iterate over the data, and to call
- 'self.close()' once the response is finished.
- """
- try:
- if not self.result_is_file() or not self.sendfile():
- for data in self.result:
- self.write(data)
- self.finish_content()
- finally:
- self.close()
-
-
- def get_scheme(self):
- """Return the URL scheme being used"""
- return guess_scheme(self.environ)
-
-
- def set_content_length(self):
- """Compute Content-Length or switch to chunked encoding if possible"""
- try:
- blocks = len(self.result)
- except (TypeError,AttributeError,NotImplementedError):
- pass
- else:
- if blocks==1:
- self.headers['Content-Length'] = str(self.bytes_sent)
- return
- # XXX Try for chunked encoding if origin server and client is 1.1
-
-
- def cleanup_headers(self):
- """Make any necessary header changes or defaults
-
- Subclasses can extend this to add other defaults.
- """
- if 'Content-Length' not in self.headers:
- self.set_content_length()
-
- def start_response(self, status, headers,exc_info=None):
- """'start_response()' callable as specified by PEP 333"""
-
- if exc_info:
- try:
- if self.headers_sent:
- # Re-raise original exception if headers sent
- raise exc_info[0], exc_info[1], exc_info[2]
- finally:
- exc_info = None # avoid dangling circular ref
- elif self.headers is not None:
- raise AssertionError("Headers already set!")
-
- assert type(status) is StringType,"Status must be a string"
- assert len(status)>=4,"Status must be at least 4 characters"
- assert int(status[:3]),"Status message must begin w/3-digit code"
- assert status[3]==" ", "Status message must have a space after code"
- if __debug__:
- for name,val in headers:
- assert type(name) is StringType,"Header names must be strings"
- assert type(val) is StringType,"Header values must be strings"
- assert not is_hop_by_hop(name),"Hop-by-hop headers not allowed"
- self.status = status
- self.headers = self.headers_class(headers)
- return self.write
-
-
- def send_preamble(self):
- """Transmit version/status/date/server, via self._write()"""
- if self.origin_server:
- if self.client_is_modern():
- self._write('HTTP/%s %s\r\n' % (self.http_version,self.status))
- if 'Date' not in self.headers:
- self._write(
- 'Date: %s\r\n' % format_date_time(time.time())
- )
- if self.server_software and 'Server' not in self.headers:
- self._write('Server: %s\r\n' % self.server_software)
- else:
- self._write('Status: %s\r\n' % self.status)
-
- def write(self, data):
- """'write()' callable as specified by PEP 333"""
-
- assert type(data) is StringType,"write() argument must be string"
-
- if not self.status:
- raise AssertionError("write() before start_response()")
-
- elif not self.headers_sent:
- # Before the first output, send the stored headers
- self.bytes_sent = len(data) # make sure we know content-length
- self.send_headers()
- else:
- self.bytes_sent += len(data)
-
- # XXX check Content-Length and truncate if too many bytes written?
- self._write(data)
- self._flush()
-
-
- def sendfile(self):
- """Platform-specific file transmission
-
- Override this method in subclasses to support platform-specific
- file transmission. It is only called if the application's
- return iterable ('self.result') is an instance of
- 'self.wsgi_file_wrapper'.
-
- This method should return a true value if it was able to actually
- transmit the wrapped file-like object using a platform-specific
- approach. It should return a false value if normal iteration
- should be used instead. An exception can be raised to indicate
- that transmission was attempted, but failed.
-
- NOTE: this method should call 'self.send_headers()' if
- 'self.headers_sent' is false and it is going to attempt direct
- transmission of the file.
- """
- return False # No platform-specific transmission by default
-
-
- def finish_content(self):
- """Ensure headers and content have both been sent"""
- if not self.headers_sent:
- # Only zero Content-Length if not set by the application (so
- # that HEAD requests can be satisfied properly, see #3839)
- self.headers.setdefault('Content-Length', "0")
- self.send_headers()
- else:
- pass # XXX check if content-length was too short?
-
- def close(self):
- """Close the iterable (if needed) and reset all instance vars
-
- Subclasses may want to also drop the client connection.
- """
- try:
- if hasattr(self.result,'close'):
- self.result.close()
- finally:
- self.result = self.headers = self.status = self.environ = None
- self.bytes_sent = 0; self.headers_sent = False
-
-
- def send_headers(self):
- """Transmit headers to the client, via self._write()"""
- self.cleanup_headers()
- self.headers_sent = True
- if not self.origin_server or self.client_is_modern():
- self.send_preamble()
- self._write(str(self.headers))
-
-
- def result_is_file(self):
- """True if 'self.result' is an instance of 'self.wsgi_file_wrapper'"""
- wrapper = self.wsgi_file_wrapper
- return wrapper is not None and isinstance(self.result,wrapper)
-
-
- def client_is_modern(self):
- """True if client can accept status and headers"""
- return self.environ['SERVER_PROTOCOL'].upper() != 'HTTP/0.9'
-
-
- def log_exception(self,exc_info):
- """Log the 'exc_info' tuple in the server log
-
- Subclasses may override to retarget the output or change its format.
- """
- try:
- from traceback import print_exception
- stderr = self.get_stderr()
- print_exception(
- exc_info[0], exc_info[1], exc_info[2],
- self.traceback_limit, stderr
- )
- stderr.flush()
- finally:
- exc_info = None
-
- def handle_error(self):
- """Log current error, and send error output to client if possible"""
- self.log_exception(sys.exc_info())
- if not self.headers_sent:
- self.result = self.error_output(self.environ, self.start_response)
- self.finish_response()
- # XXX else: attempt advanced recovery techniques for HTML or text?
-
- def error_output(self, environ, start_response):
- """WSGI mini-app to create error output
-
- By default, this just uses the 'error_status', 'error_headers',
- and 'error_body' attributes to generate an output page. It can
- be overridden in a subclass to dynamically generate diagnostics,
- choose an appropriate message for the user's preferred language, etc.
-
- Note, however, that it's not recommended from a security perspective to
- spit out diagnostics to any old user; ideally, you should have to do
- something special to enable diagnostic output, which is why we don't
- include any here!
- """
- start_response(self.error_status,self.error_headers[:],sys.exc_info())
- return [self.error_body]
-
-
- # Pure abstract methods; *must* be overridden in subclasses
-
- def _write(self,data):
- """Override in subclass to buffer data for send to client
-
- It's okay if this method actually transmits the data; BaseHandler
- just separates write and flush operations for greater efficiency
- when the underlying system actually has such a distinction.
- """
- raise NotImplementedError
-
- def _flush(self):
- """Override in subclass to force sending of recent '_write()' calls
-
- It's okay if this method is a no-op (i.e., if '_write()' actually
- sends the data.
- """
- raise NotImplementedError
-
- def get_stdin(self):
- """Override in subclass to return suitable 'wsgi.input'"""
- raise NotImplementedError
-
- def get_stderr(self):
- """Override in subclass to return suitable 'wsgi.errors'"""
- raise NotImplementedError
-
- def add_cgi_vars(self):
- """Override in subclass to insert CGI variables in 'self.environ'"""
- raise NotImplementedError
-
-
-class SimpleHandler(BaseHandler):
- """Handler that's just initialized with streams, environment, etc.
-
- This handler subclass is intended for synchronous HTTP/1.0 origin servers,
- and handles sending the entire response output, given the correct inputs.
-
- Usage::
-
- handler = SimpleHandler(
- inp,out,err,env, multithread=False, multiprocess=True
- )
- handler.run(app)"""
-
- def __init__(self,stdin,stdout,stderr,environ,
- multithread=True, multiprocess=False
- ):
- self.stdin = stdin
- self.stdout = stdout
- self.stderr = stderr
- self.base_env = environ
- self.wsgi_multithread = multithread
- self.wsgi_multiprocess = multiprocess
-
- def get_stdin(self):
- return self.stdin
-
- def get_stderr(self):
- return self.stderr
-
- def add_cgi_vars(self):
- self.environ.update(self.base_env)
-
- def _write(self,data):
- self.stdout.write(data)
- self._write = self.stdout.write
-
- def _flush(self):
- self.stdout.flush()
- self._flush = self.stdout.flush
-
-
-class BaseCGIHandler(SimpleHandler):
-
- """CGI-like systems using input/output/error streams and environ mapping
-
- Usage::
-
- handler = BaseCGIHandler(inp,out,err,env)
- handler.run(app)
-
- This handler class is useful for gateway protocols like ReadyExec and
- FastCGI, that have usable input/output/error streams and an environment
- mapping. It's also the base class for CGIHandler, which just uses
- sys.stdin, os.environ, and so on.
-
- The constructor also takes keyword arguments 'multithread' and
- 'multiprocess' (defaulting to 'True' and 'False' respectively) to control
- the configuration sent to the application. It sets 'origin_server' to
- False (to enable CGI-like output), and assumes that 'wsgi.run_once' is
- False.
- """
-
- origin_server = False
-
-
-class CGIHandler(BaseCGIHandler):
-
- """CGI-based invocation via sys.stdin/stdout/stderr and os.environ
-
- Usage::
-
- CGIHandler().run(app)
-
- The difference between this class and BaseCGIHandler is that it always
- uses 'wsgi.run_once' of 'True', 'wsgi.multithread' of 'False', and
- 'wsgi.multiprocess' of 'True'. It does not take any initialization
- parameters, but always uses 'sys.stdin', 'os.environ', and friends.
-
- If you need to override any of these parameters, use BaseCGIHandler
- instead.
- """
-
- wsgi_run_once = True
- # Do not allow os.environ to leak between requests in Google App Engine
- # and other multi-run CGI use cases. This is not easily testable.
- # See http://bugs.python.org/issue7250
- os_environ = {}
-
- def __init__(self):
- BaseCGIHandler.__init__(
- self, sys.stdin, sys.stdout, sys.stderr, dict(os.environ.items()),
- multithread=False, multiprocess=True
- )
diff --git a/contrib/tools/python/src/Lib/wsgiref/headers.py b/contrib/tools/python/src/Lib/wsgiref/headers.py
deleted file mode 100644
index 5a95e84c342..00000000000
--- a/contrib/tools/python/src/Lib/wsgiref/headers.py
+++ /dev/null
@@ -1,169 +0,0 @@
-"""Manage HTTP Response Headers
-
-Much of this module is red-handedly pilfered from email.message in the stdlib,
-so portions are Copyright (C) 2001,2002 Python Software Foundation, and were
-written by Barry Warsaw.
-"""
-
-from types import ListType, TupleType
-
-# Regular expression that matches `special' characters in parameters, the
-# existence of which force quoting of the parameter value.
-import re
-tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]')
-
-def _formatparam(param, value=None, quote=1):
- """Convenience function to format and return a key=value pair.
-
- This will quote the value if needed or if quote is true.
- """
- if value is not None and len(value) > 0:
- if quote or tspecials.search(value):
- value = value.replace('\\', '\\\\').replace('"', r'\"')
- return '%s="%s"' % (param, value)
- else:
- return '%s=%s' % (param, value)
- else:
- return param
-
-
-class Headers:
-
- """Manage a collection of HTTP response headers"""
-
- def __init__(self,headers):
- if type(headers) is not ListType:
- raise TypeError("Headers must be a list of name/value tuples")
- self._headers = headers
-
- def __len__(self):
- """Return the total number of headers, including duplicates."""
- return len(self._headers)
-
- def __setitem__(self, name, val):
- """Set the value of a header."""
- del self[name]
- self._headers.append((name, val))
-
- def __delitem__(self,name):
- """Delete all occurrences of a header, if present.
-
- Does *not* raise an exception if the header is missing.
- """
- name = name.lower()
- self._headers[:] = [kv for kv in self._headers if kv[0].lower() != name]
-
- def __getitem__(self,name):
- """Get the first header value for 'name'
-
- Return None if the header is missing instead of raising an exception.
-
- Note that if the header appeared multiple times, the first exactly which
- occurrence gets returned is undefined. Use getall() to get all
- the values matching a header field name.
- """
- return self.get(name)
-
- def has_key(self, name):
- """Return true if the message contains the header."""
- return self.get(name) is not None
-
- __contains__ = has_key
-
-
- def get_all(self, name):
- """Return a list of all the values for the named field.
-
- These will be sorted in the order they appeared in the original header
- list or were added to this instance, and may contain duplicates. Any
- fields deleted and re-inserted are always appended to the header list.
- If no fields exist with the given name, returns an empty list.
- """
- name = name.lower()
- return [kv[1] for kv in self._headers if kv[0].lower()==name]
-
-
- def get(self,name,default=None):
- """Get the first header value for 'name', or return 'default'"""
- name = name.lower()
- for k,v in self._headers:
- if k.lower()==name:
- return v
- return default
-
-
- def keys(self):
- """Return a list of all the header field names.
-
- These will be sorted in the order they appeared in the original header
- list, or were added to this instance, and may contain duplicates.
- Any fields deleted and re-inserted are always appended to the header
- list.
- """
- return [k for k, v in self._headers]
-
- def values(self):
- """Return a list of all header values.
-
- These will be sorted in the order they appeared in the original header
- list, or were added to this instance, and may contain duplicates.
- Any fields deleted and re-inserted are always appended to the header
- list.
- """
- return [v for k, v in self._headers]
-
- def items(self):
- """Get all the header fields and values.
-
- These will be sorted in the order they were in the original header
- list, or were added to this instance, and may contain duplicates.
- Any fields deleted and re-inserted are always appended to the header
- list.
- """
- return self._headers[:]
-
- def __repr__(self):
- return "Headers(%r)" % self._headers
-
- def __str__(self):
- """str() returns the formatted headers, complete with end line,
- suitable for direct HTTP transmission."""
- return '\r\n'.join(["%s: %s" % kv for kv in self._headers]+['',''])
-
- def setdefault(self,name,value):
- """Return first matching header value for 'name', or 'value'
-
- If there is no header named 'name', add a new header with name 'name'
- and value 'value'."""
- result = self.get(name)
- if result is None:
- self._headers.append((name,value))
- return value
- else:
- return result
-
- def add_header(self, _name, _value, **_params):
- """Extended header setting.
-
- _name is the header field to add. keyword arguments can be used to set
- additional parameters for the header field, with underscores converted
- to dashes. Normally the parameter will be added as key="value" unless
- value is None, in which case only the key will be added.
-
- Example:
-
- h.add_header('content-disposition', 'attachment', filename='bud.gif')
-
- Note that unlike the corresponding 'email.message' method, this does
- *not* handle '(charset, language, value)' tuples: all values must be
- strings or None.
- """
- parts = []
- if _value is not None:
- parts.append(_value)
- for k, v in _params.items():
- if v is None:
- parts.append(k.replace('_', '-'))
- else:
- parts.append(_formatparam(k.replace('_', '-'), v))
- self._headers.append((_name, "; ".join(parts)))
diff --git a/contrib/tools/python/src/Lib/wsgiref/simple_server.py b/contrib/tools/python/src/Lib/wsgiref/simple_server.py
deleted file mode 100644
index 35b98d10d87..00000000000
--- a/contrib/tools/python/src/Lib/wsgiref/simple_server.py
+++ /dev/null
@@ -1,163 +0,0 @@
-"""BaseHTTPServer that implements the Python WSGI protocol (PEP 333, rev 1.21)
-
-This is both an example of how WSGI can be implemented, and a basis for running
-simple web applications on a local machine, such as might be done when testing
-or debugging an application. It has not been reviewed for security issues,
-however, and we strongly recommend that you use a "real" web server for
-production use.
-
-For example usage, see the 'if __name__=="__main__"' block at the end of the
-module. See also the BaseHTTPServer module docs for other API information.
-"""
-
-from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
-import urllib, sys
-from wsgiref.handlers import SimpleHandler
-
-__version__ = "0.1"
-__all__ = ['WSGIServer', 'WSGIRequestHandler', 'demo_app', 'make_server']
-
-
-server_version = "WSGIServer/" + __version__
-sys_version = "Python/" + sys.version.split()[0]
-software_version = server_version + ' ' + sys_version
-
-
-class ServerHandler(SimpleHandler):
-
- server_software = software_version
-
- def close(self):
- try:
- self.request_handler.log_request(
- self.status.split(' ',1)[0], self.bytes_sent
- )
- finally:
- SimpleHandler.close(self)
-
-
-
-class WSGIServer(HTTPServer):
-
- """BaseHTTPServer that implements the Python WSGI protocol"""
-
- application = None
-
- def server_bind(self):
- """Override server_bind to store the server name."""
- HTTPServer.server_bind(self)
- self.setup_environ()
-
- def setup_environ(self):
- # Set up base environment
- env = self.base_environ = {}
- env['SERVER_NAME'] = self.server_name
- env['GATEWAY_INTERFACE'] = 'CGI/1.1'
- env['SERVER_PORT'] = str(self.server_port)
- env['REMOTE_HOST']=''
- env['CONTENT_LENGTH']=''
- env['SCRIPT_NAME'] = ''
-
- def get_app(self):
- return self.application
-
- def set_app(self,application):
- self.application = application
-
-
-
-class WSGIRequestHandler(BaseHTTPRequestHandler):
-
- server_version = "WSGIServer/" + __version__
-
- def get_environ(self):
- env = self.server.base_environ.copy()
- env['SERVER_PROTOCOL'] = self.request_version
- env['REQUEST_METHOD'] = self.command
- if '?' in self.path:
- path,query = self.path.split('?',1)
- else:
- path,query = self.path,''
-
- env['PATH_INFO'] = urllib.unquote(path)
- env['QUERY_STRING'] = query
-
- host = self.address_string()
- if host != self.client_address[0]:
- env['REMOTE_HOST'] = host
- env['REMOTE_ADDR'] = self.client_address[0]
-
- if self.headers.typeheader is None:
- env['CONTENT_TYPE'] = self.headers.type
- else:
- env['CONTENT_TYPE'] = self.headers.typeheader
-
- length = self.headers.getheader('content-length')
- if length:
- env['CONTENT_LENGTH'] = length
-
- for h in self.headers.headers:
- k,v = h.split(':',1)
- k=k.replace('-','_').upper(); v=v.strip()
- if k in env:
- continue # skip content length, type,etc.
- if 'HTTP_'+k in env:
- env['HTTP_'+k] += ','+v # comma-separate multiple headers
- else:
- env['HTTP_'+k] = v
- return env
-
- def get_stderr(self):
- return sys.stderr
-
- def handle(self):
- """Handle a single HTTP request"""
-
- self.raw_requestline = self.rfile.readline(65537)
- if len(self.raw_requestline) > 65536:
- self.requestline = ''
- self.request_version = ''
- self.command = ''
- self.send_error(414)
- return
-
- if not self.parse_request(): # An error code has been sent, just exit
- return
-
- handler = ServerHandler(
- self.rfile, self.wfile, self.get_stderr(), self.get_environ()
- )
- handler.request_handler = self # backpointer for logging
- handler.run(self.server.get_app())
-
-
-
-def demo_app(environ,start_response):
- from StringIO import StringIO
- stdout = StringIO()
- print >>stdout, "Hello world!"
- print >>stdout
- h = environ.items(); h.sort()
- for k,v in h:
- print >>stdout, k,'=', repr(v)
- start_response("200 OK", [('Content-Type','text/plain')])
- return [stdout.getvalue()]
-
-
-def make_server(
- host, port, app, server_class=WSGIServer, handler_class=WSGIRequestHandler
-):
- """Create a new WSGI server listening on `host` and `port` for `app`"""
- server = server_class((host, port), handler_class)
- server.set_app(app)
- return server
-
-
-if __name__ == '__main__':
- httpd = make_server('', 8000, demo_app)
- sa = httpd.socket.getsockname()
- print "Serving HTTP on", sa[0], "port", sa[1], "..."
- import webbrowser
- webbrowser.open('http://localhost:8000/xyz?abc')
- httpd.handle_request() # serve one request, then exit
- httpd.server_close()
diff --git a/contrib/tools/python/src/Lib/wsgiref/util.py b/contrib/tools/python/src/Lib/wsgiref/util.py
deleted file mode 100644
index 194b187a4dc..00000000000
--- a/contrib/tools/python/src/Lib/wsgiref/util.py
+++ /dev/null
@@ -1,165 +0,0 @@
-"""Miscellaneous WSGI-related Utilities"""
-
-import posixpath
-
-__all__ = [
- 'FileWrapper', 'guess_scheme', 'application_uri', 'request_uri',
- 'shift_path_info', 'setup_testing_defaults',
-]
-
-
-class FileWrapper:
- """Wrapper to convert file-like objects to iterables"""
-
- def __init__(self, filelike, blksize=8192):
- self.filelike = filelike
- self.blksize = blksize
- if hasattr(filelike,'close'):
- self.close = filelike.close
-
- def __getitem__(self,key):
- data = self.filelike.read(self.blksize)
- if data:
- return data
- raise IndexError
-
- def __iter__(self):
- return self
-
- def next(self):
- data = self.filelike.read(self.blksize)
- if data:
- return data
- raise StopIteration
-
-def guess_scheme(environ):
- """Return a guess for whether 'wsgi.url_scheme' should be 'http' or 'https'
- """
- if environ.get("HTTPS") in ('yes','on','1'):
- return 'https'
- else:
- return 'http'
-
-def application_uri(environ):
- """Return the application's base URI (no PATH_INFO or QUERY_STRING)"""
- url = environ['wsgi.url_scheme']+'://'
- from urllib import quote
-
- if environ.get('HTTP_HOST'):
- url += environ['HTTP_HOST']
- else:
- url += environ['SERVER_NAME']
-
- if environ['wsgi.url_scheme'] == 'https':
- if environ['SERVER_PORT'] != '443':
- url += ':' + environ['SERVER_PORT']
- else:
- if environ['SERVER_PORT'] != '80':
- url += ':' + environ['SERVER_PORT']
-
- url += quote(environ.get('SCRIPT_NAME') or '/')
- return url
-
-def request_uri(environ, include_query=1):
- """Return the full request URI, optionally including the query string"""
- url = application_uri(environ)
- from urllib import quote
- path_info = quote(environ.get('PATH_INFO',''),safe='/;=,')
- if not environ.get('SCRIPT_NAME'):
- url += path_info[1:]
- else:
- url += path_info
- if include_query and environ.get('QUERY_STRING'):
- url += '?' + environ['QUERY_STRING']
- return url
-
-def shift_path_info(environ):
- """Shift a name from PATH_INFO to SCRIPT_NAME, returning it
-
- If there are no remaining path segments in PATH_INFO, return None.
- Note: 'environ' is modified in-place; use a copy if you need to keep
- the original PATH_INFO or SCRIPT_NAME.
-
- Note: when PATH_INFO is just a '/', this returns '' and appends a trailing
- '/' to SCRIPT_NAME, even though empty path segments are normally ignored,
- and SCRIPT_NAME doesn't normally end in a '/'. This is intentional
- behavior, to ensure that an application can tell the difference between
- '/x' and '/x/' when traversing to objects.
- """
- path_info = environ.get('PATH_INFO','')
- if not path_info:
- return None
-
- path_parts = path_info.split('/')
- path_parts[1:-1] = [p for p in path_parts[1:-1] if p and p != '.']
- name = path_parts[1]
- del path_parts[1]
-
- script_name = environ.get('SCRIPT_NAME','')
- script_name = posixpath.normpath(script_name+'/'+name)
- if script_name.endswith('/'):
- script_name = script_name[:-1]
- if not name and not script_name.endswith('/'):
- script_name += '/'
-
- environ['SCRIPT_NAME'] = script_name
- environ['PATH_INFO'] = '/'.join(path_parts)
-
- # Special case: '/.' on PATH_INFO doesn't get stripped,
- # because we don't strip the last element of PATH_INFO
- # if there's only one path part left. Instead of fixing this
- # above, we fix it here so that PATH_INFO gets normalized to
- # an empty string in the environ.
- if name=='.':
- name = None
- return name
-
-def setup_testing_defaults(environ):
- """Update 'environ' with trivial defaults for testing purposes
-
- This adds various parameters required for WSGI, including HTTP_HOST,
- SERVER_NAME, SERVER_PORT, REQUEST_METHOD, SCRIPT_NAME, PATH_INFO,
- and all of the wsgi.* variables. It only supplies default values,
- and does not replace any existing settings for these variables.
-
- This routine is intended to make it easier for unit tests of WSGI
- servers and applications to set up dummy environments. It should *not*
- be used by actual WSGI servers or applications, since the data is fake!
- """
-
- environ.setdefault('SERVER_NAME','127.0.0.1')
- environ.setdefault('SERVER_PROTOCOL','HTTP/1.0')
-
- environ.setdefault('HTTP_HOST',environ['SERVER_NAME'])
- environ.setdefault('REQUEST_METHOD','GET')
-
- if 'SCRIPT_NAME' not in environ and 'PATH_INFO' not in environ:
- environ.setdefault('SCRIPT_NAME','')
- environ.setdefault('PATH_INFO','/')
-
- environ.setdefault('wsgi.version', (1,0))
- environ.setdefault('wsgi.run_once', 0)
- environ.setdefault('wsgi.multithread', 0)
- environ.setdefault('wsgi.multiprocess', 0)
-
- from StringIO import StringIO
- environ.setdefault('wsgi.input', StringIO(""))
- environ.setdefault('wsgi.errors', StringIO())
- environ.setdefault('wsgi.url_scheme',guess_scheme(environ))
-
- if environ['wsgi.url_scheme']=='http':
- environ.setdefault('SERVER_PORT', '80')
- elif environ['wsgi.url_scheme']=='https':
- environ.setdefault('SERVER_PORT', '443')
-
-
-
-_hoppish = {
- 'connection':1, 'keep-alive':1, 'proxy-authenticate':1,
- 'proxy-authorization':1, 'te':1, 'trailers':1, 'transfer-encoding':1,
- 'upgrade':1
-}.__contains__
-
-def is_hop_by_hop(header_name):
- """Return true if 'header_name' is an HTTP/1.1 "Hop-by-Hop" header"""
- return _hoppish(header_name.lower())
diff --git a/contrib/tools/python/src/Lib/wsgiref/validate.py b/contrib/tools/python/src/Lib/wsgiref/validate.py
deleted file mode 100644
index c3278120b0a..00000000000
--- a/contrib/tools/python/src/Lib/wsgiref/validate.py
+++ /dev/null
@@ -1,432 +0,0 @@
-# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
-# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
-# Also licenced under the Apache License, 2.0: http://opensource.org/licenses/apache2.0.php
-# Licensed to PSF under a Contributor Agreement
-"""
-Middleware to check for obedience to the WSGI specification.
-
-Some of the things this checks:
-
-* Signature of the application and start_response (including that
- keyword arguments are not used).
-
-* Environment checks:
-
- - Environment is a dictionary (and not a subclass).
-
- - That all the required keys are in the environment: REQUEST_METHOD,
- SERVER_NAME, SERVER_PORT, wsgi.version, wsgi.input, wsgi.errors,
- wsgi.multithread, wsgi.multiprocess, wsgi.run_once
-
- - That HTTP_CONTENT_TYPE and HTTP_CONTENT_LENGTH are not in the
- environment (these headers should appear as CONTENT_LENGTH and
- CONTENT_TYPE).
-
- - Warns if QUERY_STRING is missing, as the cgi module acts
- unpredictably in that case.
-
- - That CGI-style variables (that don't contain a .) have
- (non-unicode) string values
-
- - That wsgi.version is a tuple
-
- - That wsgi.url_scheme is 'http' or 'https' (@@: is this too
- restrictive?)
-
- - Warns if the REQUEST_METHOD is not known (@@: probably too
- restrictive).
-
- - That SCRIPT_NAME and PATH_INFO are empty or start with /
-
- - That at least one of SCRIPT_NAME or PATH_INFO are set.
-
- - That CONTENT_LENGTH is a positive integer.
-
- - That SCRIPT_NAME is not '/' (it should be '', and PATH_INFO should
- be '/').
-
- - That wsgi.input has the methods read, readline, readlines, and
- __iter__
-
- - That wsgi.errors has the methods flush, write, writelines
-
-* The status is a string, contains a space, starts with an integer,
- and that integer is in range (> 100).
-
-* That the headers is a list (not a subclass, not another kind of
- sequence).
-
-* That the items of the headers are tuples of strings.
-
-* That there is no 'status' header (that is used in CGI, but not in
- WSGI).
-
-* That the headers don't contain newlines or colons, end in _ or -, or
- contain characters codes below 037.
-
-* That Content-Type is given if there is content (CGI often has a
- default content type, but WSGI does not).
-
-* That no Content-Type is given when there is no content (@@: is this
- too restrictive?)
-
-* That the exc_info argument to start_response is a tuple or None.
-
-* That all calls to the writer are with strings, and no other methods
- on the writer are accessed.
-
-* That wsgi.input is used properly:
-
- - .read() is called with zero or one argument
-
- - That it returns a string
-
- - That readline, readlines, and __iter__ return strings
-
- - That .close() is not called
-
- - No other methods are provided
-
-* That wsgi.errors is used properly:
-
- - .write() and .writelines() is called with a string
-
- - That .close() is not called, and no other methods are provided.
-
-* The response iterator:
-
- - That it is not a string (it should be a list of a single string; a
- string will work, but perform horribly).
-
- - That .next() returns a string
-
- - That the iterator is not iterated over until start_response has
- been called (that can signal either a server or application
- error).
-
- - That .close() is called (doesn't raise exception, only prints to
- sys.stderr, because we only know it isn't called when the object
- is garbage collected).
-"""
-__all__ = ['validator']
-
-
-import re
-import sys
-from types import DictType, StringType, TupleType, ListType
-import warnings
-
-header_re = re.compile(r'^[a-zA-Z][a-zA-Z0-9\-_]*$')
-bad_header_value_re = re.compile(r'[\000-\037]')
-
-class WSGIWarning(Warning):
- """
- Raised in response to WSGI-spec-related warnings
- """
-
-def assert_(cond, *args):
- if not cond:
- raise AssertionError(*args)
-
-def validator(application):
-
- """
- When applied between a WSGI server and a WSGI application, this
- middleware will check for WSGI compliancy on a number of levels.
- This middleware does not modify the request or response in any
- way, but will raise an AssertionError if anything seems off
- (except for a failure to close the application iterator, which
- will be printed to stderr -- there's no way to raise an exception
- at that point).
- """
-
- def lint_app(*args, **kw):
- assert_(len(args) == 2, "Two arguments required")
- assert_(not kw, "No keyword arguments allowed")
- environ, start_response = args
-
- check_environ(environ)
-
- # We use this to check if the application returns without
- # calling start_response:
- start_response_started = []
-
- def start_response_wrapper(*args, **kw):
- assert_(len(args) == 2 or len(args) == 3, (
- "Invalid number of arguments: %s" % (args,)))
- assert_(not kw, "No keyword arguments allowed")
- status = args[0]
- headers = args[1]
- if len(args) == 3:
- exc_info = args[2]
- else:
- exc_info = None
-
- check_status(status)
- check_headers(headers)
- check_content_type(status, headers)
- check_exc_info(exc_info)
-
- start_response_started.append(None)
- return WriteWrapper(start_response(*args))
-
- environ['wsgi.input'] = InputWrapper(environ['wsgi.input'])
- environ['wsgi.errors'] = ErrorWrapper(environ['wsgi.errors'])
-
- iterator = application(environ, start_response_wrapper)
- assert_(iterator is not None and iterator != False,
- "The application must return an iterator, if only an empty list")
-
- check_iterator(iterator)
-
- return IteratorWrapper(iterator, start_response_started)
-
- return lint_app
-
-class InputWrapper:
-
- def __init__(self, wsgi_input):
- self.input = wsgi_input
-
- def read(self, *args):
- assert_(len(args) <= 1)
- v = self.input.read(*args)
- assert_(type(v) is type(""))
- return v
-
- def readline(self):
- v = self.input.readline()
- assert_(type(v) is type(""))
- return v
-
- def readlines(self, *args):
- assert_(len(args) <= 1)
- lines = self.input.readlines(*args)
- assert_(type(lines) is type([]))
- for line in lines:
- assert_(type(line) is type(""))
- return lines
-
- def __iter__(self):
- while 1:
- line = self.readline()
- if not line:
- return
- yield line
-
- def close(self):
- assert_(0, "input.close() must not be called")
-
-class ErrorWrapper:
-
- def __init__(self, wsgi_errors):
- self.errors = wsgi_errors
-
- def write(self, s):
- assert_(type(s) is type(""))
- self.errors.write(s)
-
- def flush(self):
- self.errors.flush()
-
- def writelines(self, seq):
- for line in seq:
- self.write(line)
-
- def close(self):
- assert_(0, "errors.close() must not be called")
-
-class WriteWrapper:
-
- def __init__(self, wsgi_writer):
- self.writer = wsgi_writer
-
- def __call__(self, s):
- assert_(type(s) is type(""))
- self.writer(s)
-
-class PartialIteratorWrapper:
-
- def __init__(self, wsgi_iterator):
- self.iterator = wsgi_iterator
-
- def __iter__(self):
- # We want to make sure __iter__ is called
- return IteratorWrapper(self.iterator, None)
-
-class IteratorWrapper:
-
- def __init__(self, wsgi_iterator, check_start_response):
- self.original_iterator = wsgi_iterator
- self.iterator = iter(wsgi_iterator)
- self.closed = False
- self.check_start_response = check_start_response
-
- def __iter__(self):
- return self
-
- def next(self):
- assert_(not self.closed,
- "Iterator read after closed")
- v = self.iterator.next()
- if self.check_start_response is not None:
- assert_(self.check_start_response,
- "The application returns and we started iterating over its body, but start_response has not yet been called")
- self.check_start_response = None
- return v
-
- def close(self):
- self.closed = True
- if hasattr(self.original_iterator, 'close'):
- self.original_iterator.close()
-
- def __del__(self):
- if not self.closed:
- sys.stderr.write(
- "Iterator garbage collected without being closed")
- assert_(self.closed,
- "Iterator garbage collected without being closed")
-
-def check_environ(environ):
- assert_(type(environ) is DictType,
- "Environment is not of the right type: %r (environment: %r)"
- % (type(environ), environ))
-
- for key in ['REQUEST_METHOD', 'SERVER_NAME', 'SERVER_PORT',
- 'wsgi.version', 'wsgi.input', 'wsgi.errors',
- 'wsgi.multithread', 'wsgi.multiprocess',
- 'wsgi.run_once']:
- assert_(key in environ,
- "Environment missing required key: %r" % (key,))
-
- for key in ['HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH']:
- assert_(key not in environ,
- "Environment should not have the key: %s "
- "(use %s instead)" % (key, key[5:]))
-
- if 'QUERY_STRING' not in environ:
- warnings.warn(
- 'QUERY_STRING is not in the WSGI environment; the cgi '
- 'module will use sys.argv when this variable is missing, '
- 'so application errors are more likely',
- WSGIWarning)
-
- for key in environ.keys():
- if '.' in key:
- # Extension, we don't care about its type
- continue
- assert_(type(environ[key]) is StringType,
- "Environmental variable %s is not a string: %r (value: %r)"
- % (key, type(environ[key]), environ[key]))
-
- assert_(type(environ['wsgi.version']) is TupleType,
- "wsgi.version should be a tuple (%r)" % (environ['wsgi.version'],))
- assert_(environ['wsgi.url_scheme'] in ('http', 'https'),
- "wsgi.url_scheme unknown: %r" % environ['wsgi.url_scheme'])
-
- check_input(environ['wsgi.input'])
- check_errors(environ['wsgi.errors'])
-
- # @@: these need filling out:
- if environ['REQUEST_METHOD'] not in (
- 'GET', 'HEAD', 'POST', 'OPTIONS', 'PATCH', 'PUT', 'DELETE', 'TRACE'):
- warnings.warn(
- "Unknown REQUEST_METHOD: %r" % environ['REQUEST_METHOD'],
- WSGIWarning)
-
- assert_(not environ.get('SCRIPT_NAME')
- or environ['SCRIPT_NAME'].startswith('/'),
- "SCRIPT_NAME doesn't start with /: %r" % environ['SCRIPT_NAME'])
- assert_(not environ.get('PATH_INFO')
- or environ['PATH_INFO'].startswith('/'),
- "PATH_INFO doesn't start with /: %r" % environ['PATH_INFO'])
- if environ.get('CONTENT_LENGTH'):
- assert_(int(environ['CONTENT_LENGTH']) >= 0,
- "Invalid CONTENT_LENGTH: %r" % environ['CONTENT_LENGTH'])
-
- if not environ.get('SCRIPT_NAME'):
- assert_('PATH_INFO' in environ,
- "One of SCRIPT_NAME or PATH_INFO are required (PATH_INFO "
- "should at least be '/' if SCRIPT_NAME is empty)")
- assert_(environ.get('SCRIPT_NAME') != '/',
- "SCRIPT_NAME cannot be '/'; it should instead be '', and "
- "PATH_INFO should be '/'")
-
-def check_input(wsgi_input):
- for attr in ['read', 'readline', 'readlines', '__iter__']:
- assert_(hasattr(wsgi_input, attr),
- "wsgi.input (%r) doesn't have the attribute %s"
- % (wsgi_input, attr))
-
-def check_errors(wsgi_errors):
- for attr in ['flush', 'write', 'writelines']:
- assert_(hasattr(wsgi_errors, attr),
- "wsgi.errors (%r) doesn't have the attribute %s"
- % (wsgi_errors, attr))
-
-def check_status(status):
- assert_(type(status) is StringType,
- "Status must be a string (not %r)" % status)
- # Implicitly check that we can turn it into an integer:
- status_code = status.split(None, 1)[0]
- assert_(len(status_code) == 3,
- "Status codes must be three characters: %r" % status_code)
- status_int = int(status_code)
- assert_(status_int >= 100, "Status code is invalid: %r" % status_int)
- if len(status) < 4 or status[3] != ' ':
- warnings.warn(
- "The status string (%r) should be a three-digit integer "
- "followed by a single space and a status explanation"
- % status, WSGIWarning)
-
-def check_headers(headers):
- assert_(type(headers) is ListType,
- "Headers (%r) must be of type list: %r"
- % (headers, type(headers)))
- header_names = {}
- for item in headers:
- assert_(type(item) is TupleType,
- "Individual headers (%r) must be of type tuple: %r"
- % (item, type(item)))
- assert_(len(item) == 2)
- name, value = item
- assert_(name.lower() != 'status',
- "The Status header cannot be used; it conflicts with CGI "
- "script, and HTTP status is not given through headers "
- "(value: %r)." % value)
- header_names[name.lower()] = None
- assert_('\n' not in name and ':' not in name,
- "Header names may not contain ':' or '\\n': %r" % name)
- assert_(header_re.search(name), "Bad header name: %r" % name)
- assert_(not name.endswith('-') and not name.endswith('_'),
- "Names may not end in '-' or '_': %r" % name)
- if bad_header_value_re.search(value):
- assert_(0, "Bad header value: %r (bad char: %r)"
- % (value, bad_header_value_re.search(value).group(0)))
-
-def check_content_type(status, headers):
- code = int(status.split(None, 1)[0])
- # @@: need one more person to verify this interpretation of RFC 2616
- # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
- NO_MESSAGE_BODY = (204, 304)
- for name, value in headers:
- if name.lower() == 'content-type':
- if code not in NO_MESSAGE_BODY:
- return
- assert_(0, ("Content-Type header found in a %s response, "
- "which must not return content.") % code)
- if code not in NO_MESSAGE_BODY:
- assert_(0, "No Content-Type header found in headers (%s)" % headers)
-
-def check_exc_info(exc_info):
- assert_(exc_info is None or type(exc_info) is type(()),
- "exc_info (%r) is not a tuple: %r" % (exc_info, type(exc_info)))
- # More exc_info checks?
-
-def check_iterator(iterator):
- # Technically a string is legal, which is why it's a really bad
- # idea, because it may cause the response to be returned
- # character-by-character
- assert_(not isinstance(iterator, str),
- "You should not return a string as your application iterator, "
- "instead return a single-item list containing that string.")