Merge the trunk changes in. Breaks socket.ssl for now.

Merged revisions 57392-57619 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r57395 | georg.brandl | 2007-08-24 19:23:23 +0200 (Fri, 24 Aug 2007) | 2 lines

  Bug #1011: fix rfc822.Message.getheader docs.
........
  r57397 | georg.brandl | 2007-08-24 19:38:49 +0200 (Fri, 24 Aug 2007) | 2 lines

  Patch #1006: port test_winreg to unittest.
........
  r57398 | georg.brandl | 2007-08-24 19:46:54 +0200 (Fri, 24 Aug 2007) | 2 lines

  Fix #1012: wrong URL to :mod:`site` in install/index.rst.
........
  r57399 | georg.brandl | 2007-08-24 20:07:52 +0200 (Fri, 24 Aug 2007) | 2 lines

  Patch #1008: port test_signal to unittest.
........
  r57400 | georg.brandl | 2007-08-24 20:22:54 +0200 (Fri, 24 Aug 2007) | 2 lines

  Port test_frozen to unittest.
........
  r57401 | georg.brandl | 2007-08-24 20:27:43 +0200 (Fri, 24 Aug 2007) | 2 lines

  Document new utility functions in test_support.
........
  r57402 | georg.brandl | 2007-08-24 20:30:06 +0200 (Fri, 24 Aug 2007) | 2 lines

  Remove test_rgbimg output file, there is no test_rgbimg.py.
........
  r57403 | georg.brandl | 2007-08-24 20:35:27 +0200 (Fri, 24 Aug 2007) | 2 lines

  Remove output file for test_ossaudiodev, also properly close the dsp object.
........
  r57404 | georg.brandl | 2007-08-24 20:46:27 +0200 (Fri, 24 Aug 2007) | 2 lines

  Convert test_linuxaudiodev to unittest. Fix a wrong finally clause in test_ossaudiodev.
........
  r57406 | collin.winter | 2007-08-24 21:13:58 +0200 (Fri, 24 Aug 2007) | 1 line

  Convert test_pkg to use unittest.
........
  r57408 | georg.brandl | 2007-08-24 21:22:34 +0200 (Fri, 24 Aug 2007) | 2 lines

  Catch the correct errors.
........
  r57409 | georg.brandl | 2007-08-24 21:33:53 +0200 (Fri, 24 Aug 2007) | 2 lines

  Port test_class to unittest. Patch #1671298.
........
  r57415 | collin.winter | 2007-08-24 23:09:42 +0200 (Fri, 24 Aug 2007) | 1 line

  Make test_structmembers pass when run with regrtests's -R flag.
........
  r57455 | nick.coghlan | 2007-08-25 06:32:07 +0200 (Sat, 25 Aug 2007) | 1 line

  Revert misguided attempt at fixing incompatibility between -m and -i switches (better fix coming soon)
........
  r57456 | nick.coghlan | 2007-08-25 06:35:54 +0200 (Sat, 25 Aug 2007) | 1 line

  Revert compile.c changes that shouldn't have been included in previous checkin
........
  r57461 | nick.coghlan | 2007-08-25 12:50:41 +0200 (Sat, 25 Aug 2007) | 1 line

  Fix bug 1764407 - the -i switch now does the right thing when using the -m switch
........
  r57464 | guido.van.rossum | 2007-08-25 17:08:43 +0200 (Sat, 25 Aug 2007) | 4 lines

  Server-side SSL and certificate validation, by Bill Janssen.
  While cleaning up Bill's C style, I may have cleaned up some code
  he didn't touch as well (in _ssl.c).
........
  r57465 | neal.norwitz | 2007-08-25 18:41:36 +0200 (Sat, 25 Aug 2007) | 3 lines

  Try to get this to build with Visual Studio by moving all the variable
  declarations to the beginning of a scope.
........
  r57466 | neal.norwitz | 2007-08-25 18:54:38 +0200 (Sat, 25 Aug 2007) | 1 line

  Fix test so it is skipped properly if there is no SSL support.
........
  r57467 | neal.norwitz | 2007-08-25 18:58:09 +0200 (Sat, 25 Aug 2007) | 2 lines

  Fix a few more variables to try to get this to compile with Visual Studio.
........
  r57473 | neal.norwitz | 2007-08-25 19:25:17 +0200 (Sat, 25 Aug 2007) | 1 line

  Try to get this test to pass for systems that do not have SO_REUSEPORT
........
  r57482 | gregory.p.smith | 2007-08-26 02:26:00 +0200 (Sun, 26 Aug 2007) | 7 lines

  keep setup.py from listing unneeded hash modules (_md5, _sha*) as
  missing when they were not built because _hashlib with openssl provided
  their functionality instead.

  don't build bsddb185 if bsddb was built.
........
  r57483 | neal.norwitz | 2007-08-26 03:08:16 +0200 (Sun, 26 Aug 2007) | 1 line

  Fix typo in docstring (missing c in reacquire)
........
  r57484 | neal.norwitz | 2007-08-26 03:42:03 +0200 (Sun, 26 Aug 2007) | 2 lines

  Spell check (also americanify behaviour, it's almost 3 times as common)
........
  r57503 | neal.norwitz | 2007-08-26 08:29:57 +0200 (Sun, 26 Aug 2007) | 4 lines

  Reap children before the test starts so hopefully SocketServer
  won't find any old children left around which causes an exception
  in collect_children() and the test to fail.
........
  r57510 | neal.norwitz | 2007-08-26 20:50:39 +0200 (Sun, 26 Aug 2007) | 1 line

  Fail gracefully if the cert files cannot be created
........
  r57513 | guido.van.rossum | 2007-08-26 21:35:09 +0200 (Sun, 26 Aug 2007) | 4 lines

  Bill Janssen wrote:
  Here's a patch which makes test_ssl a better player in the buildbots
  environment.  I deep-ended on "try-except-else" clauses.
........
  r57518 | neal.norwitz | 2007-08-26 23:40:16 +0200 (Sun, 26 Aug 2007) | 1 line

  Get the test passing by commenting out some writes (should they be removed?)
........
  r57522 | neal.norwitz | 2007-08-27 00:16:23 +0200 (Mon, 27 Aug 2007) | 3 lines

  Catch IOError for when the device file doesn't exist or the user doesn't have
  permission to write to the device.
........
  r57524 | neal.norwitz | 2007-08-27 00:20:03 +0200 (Mon, 27 Aug 2007) | 5 lines

  Another patch from Bill Janssen that:
  1)  Fixes the bug that two class names are initial-lower-case.
  2)  Replaces the poll waiting for the server to become ready with
      a threading.Event signal.
........
  r57536 | neal.norwitz | 2007-08-27 02:58:33 +0200 (Mon, 27 Aug 2007) | 1 line

  Stop using string.join (from the module) to ease upgrade to py3k
........
  r57537 | neal.norwitz | 2007-08-27 03:03:18 +0200 (Mon, 27 Aug 2007) | 1 line

  Make a utility function for handling (printing) an error
........
  r57538 | neal.norwitz | 2007-08-27 03:15:33 +0200 (Mon, 27 Aug 2007) | 4 lines

  If we can't create a certificate, print a warning, but don't fail the test.
  Modified patch from what Bill Janssen sent on python-3000.
........
  r57539 | facundo.batista | 2007-08-27 03:15:34 +0200 (Mon, 27 Aug 2007) | 7 lines


  Ignore test failures caused by 'resource temporarily unavailable'
  exceptions raised in the test server thread, since SimpleXMLRPCServer
  does not gracefully handle them.  Changed number of requests handled
  by tests server thread to one (was 2) because no tests require more
  than one request. [GSoC - Alan McIntyre]
........
  r57561 | guido.van.rossum | 2007-08-27 19:19:42 +0200 (Mon, 27 Aug 2007) | 8 lines

  > Regardless, building a fixed test certificate and checking it in sounds like
  > the better option.  Then the openssl command in the test code can be turned
  > into a comment describing how the test data was pregenerated.

  Here's a patch that does that.

  Bill
........
  r57568 | guido.van.rossum | 2007-08-27 20:42:23 +0200 (Mon, 27 Aug 2007) | 26 lines

  > Some of the code sets the error string in this directly before
  > returning NULL, and other pieces of the code call PySSL_SetError,
  > which creates the error string.  I think some of the places which set
  > the string directly probably shouldn't; instead, they should call
  > PySSL_SetError to cons up the error name directly from the err code.
  > However, PySSL_SetError only works after the construction of an ssl
  > object, which means it can't be used there...  I'll take a longer look
  > at it and see if there's a reasonable fix.

  Here's a patch which addresses this.  It also fixes the indentation in
  PySSL_SetError, bringing it into line with PEP 7, fixes a compile warning
  about one of the OpenSSL macros, and makes the namespace a bit more
  consistent.  I've tested it on FC 7 and OS X 10.4.

  % ./python ./Lib/test/regrtest.py -R :1: -u all test_ssl
  test_ssl
  beginning 6 repetitions
  123456
  ......
  1 test OK.
  [29244 refs]
  %

  [GvR: slightly edited to enforce 79-char line length, even if it required
   violating the style guide.]
........
  r57570 | guido.van.rossum | 2007-08-27 21:11:11 +0200 (Mon, 27 Aug 2007) | 2 lines

  Patch 10124 by Bill Janssen, docs for the new ssl code.
........
  r57574 | guido.van.rossum | 2007-08-27 22:51:00 +0200 (Mon, 27 Aug 2007) | 3 lines

  Patch # 1739906 by Christian Heimes -- add reduce to functools (importing
  it from __builtin__).
........
  r57575 | guido.van.rossum | 2007-08-27 22:52:10 +0200 (Mon, 27 Aug 2007) | 2 lines

  News about functools.reduce.
........
  r57611 | georg.brandl | 2007-08-28 10:29:08 +0200 (Tue, 28 Aug 2007) | 2 lines

  Document rev. 57574.
........
  r57612 | sean.reifschneider | 2007-08-28 11:07:54 +0200 (Tue, 28 Aug 2007) | 2 lines

  Adding basic imputil documentation.
........
  r57614 | georg.brandl | 2007-08-28 12:48:18 +0200 (Tue, 28 Aug 2007) | 2 lines

  Fix some glitches.
........
  r57616 | lars.gustaebel | 2007-08-28 14:31:09 +0200 (Tue, 28 Aug 2007) | 5 lines

  TarFile.__init__() no longer fails if no name argument is passed and
  the fileobj argument has no usable name attribute (e.g. StringIO).

  (will backport to 2.5)
........
  r57619 | thomas.wouters | 2007-08-28 17:28:19 +0200 (Tue, 28 Aug 2007) | 22 lines


  Improve extended slicing support in builtin types and classes. Specifically:

   - Specialcase extended slices that amount to a shallow copy the same way as
     is done for simple slices, in the tuple, string and unicode case.

   - Specialcase step-1 extended slices to optimize the common case for all
     involved types.

   - For lists, allow extended slice assignment of differing lengths as long
     as the step is 1. (Previously, 'l[:2:1] = []' failed even though
     'l[:2] = []' and 'l[:2:None] = []' do not.)

   - Implement extended slicing for buffer, array, structseq, mmap and
     UserString.UserString.

   - Implement slice-object support (but not non-step-1 slice assignment) for
     UserString.MutableString.

   - Add tests for all new functionality.
........
This commit is contained in:
Thomas Wouters 2007-08-28 21:37:11 +00:00
parent 9e7c8da61c
commit ed03b4121e
56 changed files with 3587 additions and 1146 deletions

View file

@ -604,8 +604,6 @@ value of ``sys.path``. ::
The null string in ``sys.path`` represents the current working directory.
.. % $ <-- bow to font-lock
The expected convention for locally installed packages is to put them in the
:file:`{...}/site-packages/` directory, but you may want to install Python
modules into some arbitrary directory. For example, your site may have a
@ -624,9 +622,8 @@ installing fixed versions of standard modules.)
Paths can be absolute or relative, in which case they're relative to the
directory containing the :file:`.pth` file. Any directories added to the search
path will be scanned in turn for :file:`.pth` files. See `site module
documentation <http://www.python.org/dev/doc/devel/lib/module-site.html>`_ for
more information.
path will be scanned in turn for :file:`.pth` files. See the documentation of
the :mod:`site` module for more information.
A slightly less convenient way is to edit the :file:`site.py` file in Python's
standard library, and modify ``sys.path``. :file:`site.py` is automatically

View file

@ -109,7 +109,7 @@ UNICODE is defined or not::
*windll* does not try to select one of them by magic, you must access the
version you need by specifying ``GetModuleHandleA`` or ``GetModuleHandleW``
explicitely, and then call it with normal strings or unicode strings
explicitly, and then call it with normal strings or unicode strings
respectively.
Sometimes, dlls export functions with names which aren't valid Python
@ -383,7 +383,7 @@ course, it must be one of integer, string, or unicode::
If you don't want to store the instance's data in the :attr:`_as_parameter_`
instance variable, you could define a ``property`` which makes the data
avaiblable.
available.
.. _ctypes-specifying-required-argument-types:
@ -600,7 +600,7 @@ Structure/union alignment and byte order
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
By default, Structure and Union fields are aligned in the same way the C
compiler does it. It is possible to override this behaviour be specifying a
compiler does it. It is possible to override this behavior be specifying a
:attr:`_pack_` class attribute in the subclass definition. This must be set to a
positive integer and specifies the maximum alignment for the fields. This is
what ``#pragma pack(n)`` also does in MSVC.
@ -643,7 +643,7 @@ positive integer::
TenPointsArrayType = POINT * 10
Here is an example of an somewhat artifical data type, a structure containing 4
Here is an example of an somewhat artificial data type, a structure containing 4
POINTs among other stuff::
>>> from ctypes import *
@ -1134,7 +1134,7 @@ hit the NULL entry::
>>>
The fact that standard Python has a frozen module and a frozen package
(indicated by the negative size member) is not wellknown, it is only used for
(indicated by the negative size member) is not well known, it is only used for
testing. Try it out with ``import __hello__`` for example.
@ -1167,7 +1167,7 @@ Consider the following example::
>>>
Hm. We certainly expected the last statement to print ``3 4 1 2``. What
happended? Here are the steps of the ``rc.a, rc.b = rc.b, rc.a`` line above::
happened? Here are the steps of the ``rc.a, rc.b = rc.b, rc.a`` line above::
>>> temp0, temp1 = rc.b, rc.a
>>> rc.a = temp0
@ -1180,8 +1180,8 @@ contents of ``temp0`` into ``rc`` 's buffer. This, in turn, changes the
contents of ``temp1``. So, the last assignment ``rc.b = temp1``, doesn't have
the expected effect.
Keep in mind that retrieving subobjects from Structure, Unions, and Arrays
doesn't *copy* the subobject, instead it retrieves a wrapper object accessing
Keep in mind that retrieving sub-objects from Structure, Unions, and Arrays
doesn't *copy* the sub-object, instead it retrieves a wrapper object accessing
the root-object's underlying buffer.
Another example that may behave different from what one would expect is this::
@ -1292,11 +1292,11 @@ library to load.
is the form used for the posix linker option :option:`-l`). If no library can
be found, returns ``None``.
The exact functionality is system dependend.
The exact functionality is system dependent.
On Linux, ``find_library`` tries to run external programs (/sbin/ldconfig, gcc,
and objdump) to find the library file. It returns the filename of the library
file. Here are sone examples::
file. Here are some examples::
>>> from ctypes.util import find_library
>>> find_library("m")
@ -1308,7 +1308,7 @@ file. Here are sone examples::
>>>
On OS X, ``find_library`` tries several predefined naming schemes and paths to
locate the library, and returns a full pathname if successfull::
locate the library, and returns a full pathname if successful::
>>> from ctypes.util import find_library
>>> find_library("c")
@ -1367,7 +1367,7 @@ way is to instantiate one of the following classes:
platform.
The Python GIL is released before calling any function exported by these
libraries, and reaquired afterwards.
libraries, and reacquired afterwards.
.. class:: PyDLL(name, mode=DEFAULT_MODE, handle=None)
@ -1411,7 +1411,7 @@ details, consult the ``dlopen(3)`` manpage, on Windows, *mode* is ignored.
*RTLD_GLOBAL*, otherwise it is the same as *RTLD_LOCAL*.
Instances of these classes have no public methods, however :meth:`__getattr__`
and :meth:`__getitem__` have special behaviour: functions exported by the shared
and :meth:`__getitem__` have special behavior: functions exported by the shared
library can be accessed as attributes of by index. Please note that both
:meth:`__getattr__` and :meth:`__getitem__` cache their result, so calling them
repeatedly returns the same object each time.
@ -1427,7 +1427,7 @@ underscore to not clash with exported function names:
.. attribute:: PyDLL._name
The name of the library passed in the contructor.
The name of the library passed in the constructor.
Shared libraries can also be loaded by using one of the prefabricated objects,
which are instances of the :class:`LibraryLoader` class, either by calling the
@ -1440,7 +1440,7 @@ loader instance.
Class which loads shared libraries. ``dlltype`` should be one of the
:class:`CDLL`, :class:`PyDLL`, :class:`WinDLL`, or :class:`OleDLL` types.
:meth:`__getattr__` has special behaviour: It allows to load a shared library by
:meth:`__getattr__` has special behavior: It allows to load a shared library by
accessing it as attribute of a library loader instance. The result is cached,
so repeated attribute accesses return the same library each time.
@ -1508,7 +1508,7 @@ They are instances of a private class:
Instances of foreign functions are also C compatible data types; they represent
C function pointers.
This behaviour can be customized by assigning to special attributes of the
This behavior can be customized by assigning to special attributes of the
foreign function object.
@ -1520,7 +1520,7 @@ foreign function object.
It is possible to assign a callable Python object that is not a ctypes type, in
this case the function is assumed to return a C ``int``, and the callable will
be called with this integer, allowing to do further processing or error
checking. Using this is deprecated, for more flexible postprocessing or error
checking. Using this is deprecated, for more flexible post processing or error
checking use a ctypes data type as :attr:`restype` and assign a callable to the
:attr:`errcheck` attribute.
@ -1558,10 +1558,10 @@ foreign function object.
:attr:`restype` attribute.
``func`` is the foreign function object itself, this allows to reuse the same
callable object to check or postprocess the results of several functions.
callable object to check or post process the results of several functions.
``arguments`` is a tuple containing the parameters originally passed to the
function call, this allows to specialize the behaviour on the arguments used.
function call, this allows to specialize the behavior on the arguments used.
The object that this function returns will be returned from the foreign function
call, but it can also check the result value and raise an exception if the
@ -1634,7 +1634,7 @@ different ways, depending on the type and number of the parameters in the call.
:noindex:
Returns a foreign function that will call a COM method. ``vtbl_index`` is the
index into the virtual function table, a small nonnegative integer. *name* is
index into the virtual function table, a small non-negative integer. *name* is
name of the COM method. *iid* is an optional pointer to the interface identifier
which is used in extended error reporting.
@ -1827,14 +1827,14 @@ Utility functions
.. function:: DllCanUnloadNow()
Windows only: This function is a hook which allows to implement inprocess COM
Windows only: This function is a hook which allows to implement in-process COM
servers with ctypes. It is called from the DllCanUnloadNow function that the
_ctypes extension dll exports.
.. function:: DllGetClassObject()
Windows only: This function is a hook which allows to implement inprocess COM
Windows only: This function is a hook which allows to implement in-process COM
servers with ctypes. It is called from the DllGetClassObject function that the
``_ctypes`` extension dll exports.
@ -1920,7 +1920,7 @@ Utility functions
Windows only: this function is probably the worst-named thing in ctypes. It
creates an instance of WindowsError. If *code* is not specified,
``GetLastError`` is called to determine the error code. If ``descr`` is not
spcified, :func:`FormatError` is called to get a textual description of the
specified, :func:`FormatError` is called to get a textual description of the
error.
@ -1982,13 +1982,13 @@ Common instance variables of ctypes data types:
Sometimes ctypes data instances do not own the memory block they contain,
instead they share part of the memory block of a base object. The
:attr:`_b_base_` readonly member is the root ctypes object that owns the memory
:attr:`_b_base_` read-only member is the root ctypes object that owns the memory
block.
.. attribute:: _CData._b_needsfree_
This readonly variable is true when the ctypes data instance has allocated the
This read-only variable is true when the ctypes data instance has allocated the
memory block itself, false otherwise.
@ -2033,7 +2033,7 @@ converted to native Python types. In other words, if a foreign function has a
:attr:`restype` of :class:`c_char_p`, you will always receive a Python string,
*not* a :class:`c_char_p` instance.
Subclasses of fundamental data types do *not* inherit this behaviour. So, if a
Subclasses of fundamental data types do *not* inherit this behavior. So, if a
foreign functions :attr:`restype` is a subclass of :class:`c_void_p`, you will
receive an instance of this subclass from the function call. Of course, you can
get the value of the pointer by accessing the ``value`` attribute.

View file

@ -15,7 +15,15 @@ The :mod:`functools` module is for higher-order functions: functions that act on
or return other functions. In general, any callable object can be treated as a
function for the purposes of this module.
The :mod:`functools` module defines the following function:
The :mod:`functools` module defines the following functions:
.. function:: reduce(function, iterable[, initializer])
This is the same function as :func:`reduce`. It is made available in this module
to allow writing code more forward-compatible with Python 3.
.. versionadded:: 2.6
.. function:: partial(func[,*args][, **keywords])

234
Doc/library/imputil.rst Normal file
View file

@ -0,0 +1,234 @@
:mod:`imputil` --- Import utilities
=====================================================
.. module:: imputil
:synopsis: Manage and augment the import process.
.. index:: statement: import
This module provides a very handy and useful mechanism for custom
:keyword:`import` hooks. Compared to the older :mod:`ihooks` module,
:mod:`imputil` takes a dramatically simpler and more straight-forward
approach to custom :keyword:`import` functions.
.. class:: ImportManager([fs_imp])
Manage the import process.
.. method:: ImportManager.install([namespace])
Install this ImportManager into the specified namespace.
.. method:: ImportManager.uninstall()
Restore the previous import mechanism.
.. method:: ImportManager.add_suffix(suffix, importFunc)
Undocumented.
.. class:: Importer()
Base class for replacing standard import functions.
.. method:: Importer.import_top(name)
Import a top-level module.
.. method:: Importer.get_code(parent, modname, fqname)
Find and retrieve the code for the given module.
*parent* specifies a parent module to define a context for importing.
It may be ``None``, indicating no particular context for the search.
*modname* specifies a single module (not dotted) within the parent.
*fqname* specifies the fully-qualified module name. This is a
(potentially) dotted name from the "root" of the module namespace
down to the modname.
If there is no parent, then modname==fqname.
This method should return ``None``, or a 3-tuple.
* If the module was not found, then ``None`` should be returned.
* The first item of the 2- or 3-tuple should be the integer 0 or 1,
specifying whether the module that was found is a package or not.
* The second item is the code object for the module (it will be
executed within the new module's namespace). This item can also
be a fully-loaded module object (e.g. loaded from a shared lib).
* The third item is a dictionary of name/value pairs that will be
inserted into new module before the code object is executed. This
is provided in case the module's code expects certain values (such
as where the module was found). When the second item is a module
object, then these names/values will be inserted *after* the module
has been loaded/initialized.
.. class:: BuiltinImporter()
Emulate the import mechanism for builtin and frozen modules. This is a
sub-class of the :class:`Importer` class.
.. method:: BuiltinImporter.get_code(parent, modname, fqname)
Undocumented.
.. function:: py_suffix_importer(filename, finfo, fqname)
Undocumented.
.. class:: DynLoadSuffixImporter([desc])
Undocumented.
.. method:: DynLoadSuffixImporter.import_file(filename, finfo, fqname)
Undocumented.
.. _examples-imputil:
Examples
--------
This is a re-implementation of hierarchical module import.
This code is intended to be read, not executed. However, it does work
-- all you need to do to enable it is "import knee".
(The name is a pun on the klunkier predecessor of this module, "ni".)
::
import sys, imp, __builtin__
# Replacement for __import__()
def import_hook(name, globals=None, locals=None, fromlist=None):
parent = determine_parent(globals)
q, tail = find_head_package(parent, name)
m = load_tail(q, tail)
if not fromlist:
return q
if hasattr(m, "__path__"):
ensure_fromlist(m, fromlist)
return m
def determine_parent(globals):
if not globals or not globals.has_key("__name__"):
return None
pname = globals['__name__']
if globals.has_key("__path__"):
parent = sys.modules[pname]
assert globals is parent.__dict__
return parent
if '.' in pname:
i = pname.rfind('.')
pname = pname[:i]
parent = sys.modules[pname]
assert parent.__name__ == pname
return parent
return None
def find_head_package(parent, name):
if '.' in name:
i = name.find('.')
head = name[:i]
tail = name[i+1:]
else:
head = name
tail = ""
if parent:
qname = "%s.%s" % (parent.__name__, head)
else:
qname = head
q = import_module(head, qname, parent)
if q: return q, tail
if parent:
qname = head
parent = None
q = import_module(head, qname, parent)
if q: return q, tail
raise ImportError, "No module named " + qname
def load_tail(q, tail):
m = q
while tail:
i = tail.find('.')
if i < 0: i = len(tail)
head, tail = tail[:i], tail[i+1:]
mname = "%s.%s" % (m.__name__, head)
m = import_module(head, mname, m)
if not m:
raise ImportError, "No module named " + mname
return m
def ensure_fromlist(m, fromlist, recursive=0):
for sub in fromlist:
if sub == "*":
if not recursive:
try:
all = m.__all__
except AttributeError:
pass
else:
ensure_fromlist(m, all, 1)
continue
if sub != "*" and not hasattr(m, sub):
subname = "%s.%s" % (m.__name__, sub)
submod = import_module(sub, subname, m)
if not submod:
raise ImportError, "No module named " + subname
def import_module(partname, fqname, parent):
try:
return sys.modules[fqname]
except KeyError:
pass
try:
fp, pathname, stuff = imp.find_module(partname,
parent and parent.__path__)
except ImportError:
return None
try:
m = imp.load_module(fqname, fp, pathname, stuff)
finally:
if fp: fp.close()
if parent:
setattr(parent, partname, m)
return m
# Replacement for reload()
def reload_hook(module):
name = module.__name__
if '.' not in name:
return import_module(name, name, None)
i = name.rfind('.')
pname = name[:i]
parent = sys.modules[pname]
return import_module(name[i+1:], name, parent)
# Save the original hooks
original_import = __builtin__.__import__
original_reload = __builtin__.reload
# Now install our hooks
__builtin__.__import__ = import_hook
__builtin__.reload = reload_hook
.. index::
module: knee
Also see the :mod:`importers` module (which can be found
in :file:`Demo/imputil/` in the Python source distribution) for additional
examples.

View file

@ -19,6 +19,7 @@ The list of modules described in this chapter is:
subprocess.rst
socket.rst
ssl.rst
signal.rst
asyncore.rst
asynchat.rst

View file

@ -14,6 +14,7 @@ The full list of modules described in this chapter is:
.. toctree::
imp.rst
imputil.rst
zipimport.rst
pkgutil.rst
modulefinder.rst

View file

@ -198,10 +198,12 @@ A :class:`Message` instance has the following methods:
.. method:: Message.getheader(name[, default])
Like ``getrawheader(name)``, but strip leading and trailing whitespace.
Return a single string consisting of the last header matching *name*,
but strip leading and trailing whitespace.
Internal whitespace is not stripped. The optional *default* argument can be
used to specify a different default to be returned when there is no header
matching *name*.
matching *name*; it defaults to ``None``.
This is the preferred way to get parsed headers.
.. method:: Message.get(name[, default])

View file

@ -52,11 +52,9 @@ The :mod:`runpy` module provides a single function:
If the argument *alter_sys* is supplied and evaluates to ``True``, then
``sys.argv[0]`` is updated with the value of ``__file__`` and
``sys.modules[__name__]`` is updated with a new module object for the module
being executed. Note that neither ``sys.argv[0]`` nor ``sys.modules[__name__]``
are restored to their original values before the function returns -- if client
code needs these values preserved, it must either save them explicitly or
else avoid enabling the automatic alterations to :mod:`sys`.
``sys.modules[__name__]`` is updated with a temporary module object for the
module being executed. Both ``sys.argv[0]`` and ``sys.modules[__name__]``
are restored to their original values before the function returns.
Note that this manipulation of :mod:`sys` is not thread-safe. Other threads may
see the partially initialised module, as well as the altered list of arguments.

View file

@ -300,17 +300,6 @@ The module :mod:`socket` exports the following constants and functions:
omitted in that case.
.. function:: ssl(sock[, keyfile, certfile])
Initiate a SSL connection over the socket *sock*. *keyfile* is the name of a PEM
formatted file that contains your private key. *certfile* is a PEM formatted
certificate chain file. On success, a new :class:`SSLObject` is returned.
.. warning::
This does not do any certificate verification!
.. function:: socketpair([family[, type[, proto]]])
Build a pair of connected socket objects using the given address family, socket
@ -752,40 +741,6 @@ values given to the :class:`socket` constructor.
.. versionadded:: 2.5
.. _ssl-objects:
SSL Objects
-----------
SSL objects have the following methods.
.. method:: SSL.write(s)
Writes the string *s* to the on the object's SSL connection. The return value is
the number of bytes written.
.. method:: SSL.read([n])
If *n* is provided, read *n* bytes from the SSL connection, otherwise read until
EOF. The return value is a string of the bytes read.
.. method:: SSL.server()
Returns a string describing the server's certificate. Useful for debugging
purposes; do not parse the content of this string because its format can't be
parsed unambiguously.
.. method:: SSL.issuer()
Returns a string describing the issuer of the server's certificate. Useful for
debugging purposes; do not parse the content of this string because its format
can't be parsed unambiguously.
.. _socket-example:
Example
@ -903,39 +858,3 @@ sends traffic to the first one connected successfully. ::
s.close()
print 'Received', repr(data)
This example connects to an SSL server, prints the server and issuer's
distinguished names, sends some bytes, and reads part of the response::
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('www.verisign.com', 443))
ssl_sock = socket.ssl(s)
print repr(ssl_sock.server())
print repr(ssl_sock.issuer())
# Set a simple HTTP request -- use httplib in actual code.
ssl_sock.write("""GET / HTTP/1.0\r
Host: www.verisign.com\r\n\r\n""")
# Read a chunk of data. Will not necessarily
# read all the data returned by the server.
data = ssl_sock.read()
# Note that you need to close the underlying socket, not the SSL object.
del ssl_sock
s.close()
At this writing, this SSL example prints the following output (line breaks
inserted for readability)::
'/C=US/ST=California/L=Mountain View/
O=VeriSign, Inc./OU=Production Services/
OU=Terms of use at www.verisign.com/rpa (c)00/
CN=www.verisign.com'
'/O=VeriSign Trust Network/OU=VeriSign, Inc./
OU=VeriSign International Server CA - Class 3/
OU=www.verisign.com/CPS Incorp.by Ref. LIABILITY LTD.(c)97 VeriSign'

319
Doc/library/ssl.rst Normal file
View file

@ -0,0 +1,319 @@
:mod:`ssl` --- SSL wrapper for socket objects, and utility functions
====================================================================
.. module:: ssl
:synopsis: SSL wrapper for socket objects, and utility functions
.. versionadded:: 2.6
This module provides access to Transport Layer Security (often known
as "Secure Sockets Layer") encryption and peer authentication
facilities for network sockets, both client-side and server-side.
This module uses the OpenSSL library. It is available on all modern
Unix systems, Windows, Mac OS X, and probably additional
platforms, as long as OpenSSL is installed on that platform.
.. note::
Some behavior may be platform dependent, since calls are made to the operating
system socket APIs.
This section documents the objects and functions in the `ssl` module;
for more general information about TLS, SSL, and certificates, the
reader is referred to the paper, *Introducing SSL and Certificates using OpenSSL*, by Frederick J. Hirsch, at
http://old.pseudonym.org/ssl/wwwj-index.html.
This module defines a class, :class:`ssl.sslsocket`, which is
derived from the :class:`socket.socket` type, and supports additional
:meth:`read` and :meth:`write` methods, along with a method, :meth:`getpeercert`,
to retrieve the certificate of the other side of the connection.
This module defines the following functions, exceptions, and constants:
.. function:: cert_time_to_seconds(timestring)
Returns a floating-point value containing a normal seconds-after-the-epoch time
value, given the time-string representing the "notBefore" or "notAfter" date
from a certificate.
Here's an example::
>>> import ssl
>>> ssl.cert_time_to_seconds("May 9 00:00:00 2007 GMT")
1178694000.0
>>> import time
>>> time.ctime(ssl.cert_time_to_seconds("May 9 00:00:00 2007 GMT"))
'Wed May 9 00:00:00 2007'
>>>
.. exception:: sslerror
Raised to signal an error from the underlying SSL implementation. This
signifies some problem in the higher-level
encryption and authentication layer that's superimposed on the underlying
network connection.
.. data:: CERT_NONE
Value to pass to the `cert_reqs` parameter to :func:`sslobject`
when no certificates will be required or validated from the other
side of the socket connection.
.. data:: CERT_OPTIONAL
Value to pass to the `cert_reqs` parameter to :func:`sslobject`
when no certificates will be required from the other side of the
socket connection, but if they are provided, will be validated.
Note that use of this setting requires a valid certificate
validation file also be passed as a value of the `ca_certs`
parameter.
.. data:: CERT_REQUIRED
Value to pass to the `cert_reqs` parameter to :func:`sslobject`
when certificates will be required from the other side of the
socket connection. Note that use of this setting requires a valid certificate
validation file also be passed as a value of the `ca_certs`
parameter.
.. data:: PROTOCOL_SSLv2
Selects SSL version 2 as the channel encryption protocol.
.. data:: PROTOCOL_SSLv23
Selects SSL version 2 or 3 as the channel encryption protocol. This is a setting to use for maximum compatibility
with the other end of an SSL connection, but it may cause the specific ciphers chosen for the encryption to be
of fairly low quality.
.. data:: PROTOCOL_SSLv3
Selects SSL version 3 as the channel encryption protocol.
.. data:: PROTOCOL_TLSv1
Selects SSL version 2 as the channel encryption protocol. This is
the most modern version, and probably the best choice for maximum
protection, if both sides can speak it.
Certificates
------------
Certificates in general are part of a public-key / private-key system. In this system, each `principal`,
(which may be a machine, or a person, or an organization) is assigned a unique two-part encryption key.
One part of the key is public, and is called the *public key*; the other part is kept secret, and is called
the *private key*. The two parts are related, in that if you encrypt a message with one of the parts, you can
decrypt it with the other part, and **only** with the other part.
A certificate contains information about two principals. It contains
the name of a *subject*, and the subject's public key. It also
contains a statement by a second principal, the *issuer*, that the
subject is who he claims to be, and that this is indeed the subject's
public key. The issuer's statement is signed with the issuer's
private key, which only the issuer knows. However, anyone can verify
the issuer's statement by finding the issuer's public key, decrypting
the statement with it, and comparing it to the other information in
the certificate. The certificate also contains information about the
time period over which it is valid. This is expressed as two fields,
called "notBefore" and "notAfter".
The underlying system which is used in the Python SSL support is
called "OpenSSL". It contains facilities for constructing and
validating certificates. In the Python use of certificates, the other
side of a network connection can be required to produce a certificate,
and that certificate can be validated against a file filled with
self-signed *root* certificates (so-called because the issuer is the
same as the subject), and and "CA" (certification authority)
certificates assured by those root certificates (and by other CA
certificates). Either side of a connection, client or server, can
request certificates and validation, and the connection can be optionally
set up to fail if a valid certificate is not presented by the other side.
sslsocket Objects
-----------------
.. class:: sslsocket(sock [, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE, ssl_version=PROTOCOL_SSLv23, ca_certs=None])
Takes an instance *sock* of :class:`socket.socket`, and returns an instance of a subtype
of :class:`socket.socket` which wraps the underlying socket in an SSL context.
For client-side sockets, the context construction is lazy; if the underlying socket isn't
connected yet, the context construction will be performed after :meth:`connect` is called
on the socket.
The `keyfile` and `certfile` parameters specify optional files which contain a certificate
to be used to identify the local side of the connection. Often the private key is stored
in the same file as the certificate; in this case, only the `certfile` parameter need be
passed. If the private key is stored in a separate file, both parameters must be used.
The parameter `server_side` is a boolean which identifies whether server-side or client-side
behavior is desired from this socket.
The parameter `cert_reqs` specifies whether a certificate is
required from the other side of the connection, and whether it will
be validated if provided. It must be one of the three values
:const:`CERT_NONE` (certificates ignored), :const:`CERT_OPTIONAL` (not required,
but validated if provided), or :const:`CERT_REQUIRED` (required and
validated). If the value of this parameter is not :const:`CERT_NONE`, then
the `ca_certs` parameter must point to a file of CA certificates.
The parameter `ssl_version` specifies which version of the SSL protocol to use. Typically,
the server specifies this, and a client connecting to it must use the same protocol. An
SSL server using :const:`PROTOCOL_SSLv23` can understand a client connecting via SSL2, SSL3, or TLS1,
but a client using :const:`PROTOCOL_SSLv23` can only connect to an SSL2 server.
The `ca_certs` file contains a set of concatenated "certification authority" certificates,
which are used to validate certificates passed from the other end of the connection.
This file
contains the certificates in PEM format (IETF RFC 1422) where each certificate is
encoded in base64 encoding and surrounded with a header and footer::
-----BEGIN CERTIFICATE-----
... (CA certificate in base64 encoding) ...
-----END CERTIFICATE-----
The various certificates in the file are just concatenated together::
-----BEGIN CERTIFICATE-----
... (CA certificate in base64 encoding) ...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
... (a second CA certificate in base64 encoding) ...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
... (a root certificate in base64 encoding) ...
-----END CERTIFICATE-----
Some "standard" root certificates are available at
http://www.thawte.com/roots/ (for Thawte roots) and
http://www.verisign.com/support/roots.html (for Verisign roots).
.. method:: sslsocket.read([nbytes])
Reads up to `nbytes` bytes from the SSL-encrypted channel and returns them.
.. method:: sslsocket.write(data)
Writes the `data` to the other side of the connection, using the SSL channel to encrypt. Returns the number
of bytes written.
.. method:: sslsocket.getpeercert()
If there is no certificate for the peer on the other end of the connection, returns `None`.
If a certificate was received from the peer, but not validated, returns an empty `dict` instance.
If a certificate was received and validated, returns a `dict` instance with the fields
`subject` (the principal for which the certificate was issued), `issuer` (the signer of
the certificate), `notBefore` (the time before which the certificate should not be trusted),
and `notAfter` (the time after which the certificate should not be trusted) filled in.
The "subject" and "issuer" fields are themselves dictionaries containing the fields given
in the certificate's data structure for each principal::
{'issuer': {'commonName': u'somemachine.python.org',
'countryName': u'US',
'localityName': u'Wilmington',
'organizationName': u'Python Software Foundation',
'organizationalUnitName': u'SSL',
'stateOrProvinceName': u'Delaware'},
'subject': {'commonName': u'somemachine.python.org',
'countryName': u'US',
'localityName': u'Wilmington',
'organizationName': u'Python Software Foundation',
'organizationalUnitName': u'SSL',
'stateOrProvinceName': u'Delaware'},
'notAfter': 'Sep 4 21:54:26 2007 GMT',
'notBefore': 'Aug 25 21:54:26 2007 GMT',
'version': 2}
This certificate is said to be *self-signed*, because the subject
and issuer are the same entity. The *version* field refers the the X509 version
that's used for the certificate.
Examples
--------
This example connects to an SSL server, prints the server's address and certificate,
sends some bytes, and reads part of the response::
import socket, ssl, pprint
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = ssl.sslsocket(s, ca_certs="/etc/ca_certs_file", cert_reqs=ssl.CERT_REQUIRED)
ssl_sock.connect(('www.verisign.com', 443))
print repr(ssl_sock.getpeername())
print pprint.pformat(ssl_sock.getpeercert())
# Set a simple HTTP request -- use httplib in actual code.
ssl_sock.write("""GET / HTTP/1.0\r
Host: www.verisign.com\r\n\r\n""")
# Read a chunk of data. Will not necessarily
# read all the data returned by the server.
data = ssl_sock.read()
# note that closing the sslsocket will also close the underlying socket
ssl_sock.close()
As of August 25, 2007, the certificate printed by this program
looked like this::
{'issuer': {'commonName': u'VeriSign Class 3 Extended Validation SSL SGC CA',
'countryName': u'US',
'organizationName': u'VeriSign, Inc.',
'organizationalUnitName': u'Terms of use at https://www.verisign.com/rpa (c)06'},
'subject': {'1.3.6.1.4.1.311.60.2.1.2': u'Delaware',
'1.3.6.1.4.1.311.60.2.1.3': u'US',
'commonName': u'www.verisign.com',
'countryName': u'US',
'localityName': u'Mountain View',
'organizationName': u'VeriSign, Inc.',
'organizationalUnitName': u'Terms of use at www.verisign.com/rpa (c)06',
'postalCode': u'94043',
'serialNumber': u'2497886',
'stateOrProvinceName': u'California',
'streetAddress': u'487 East Middlefield Road'},
'notAfter': 'May 8 23:59:59 2009 GMT',
'notBefore': 'May 9 00:00:00 2007 GMT',
'version': 2}
For server operation, typically you'd need to have a server certificate, and private key, each in a file.
You'd open a socket, bind it to a port, call :meth:`listen` on it, then start waiting for clients
to connect::
import socket, ssl
bindsocket = socket.socket()
bindsocket.bind(('myaddr.mydomain.com', 10023))
bindsocket.listen(5)
When one did, you'd call :meth:`accept` on the socket to get the new socket from the other
end, and use :func:`sslsocket` to create a server-side SSL context for it::
while True:
newsocket, fromaddr = bindsocket.accept()
connstream = ssl.sslsocket(newsocket, server_side=True, certfile="mycertfile",
keyfile="mykeyfile", ssl_protocol=ssl.PROTOCOL_TLSv1)
deal_with_client(connstream)
Then you'd read data from the `connstream` and do something with it till you are finished with the client (or the client is finished with you)::
def deal_with_client(connstream):
data = connstream.read()
# null data means the client is finished with us
while data:
if not do_something(connstream, data):
# we'll assume do_something returns False when we're finished with client
break
data = connstream.read()
# finished with client
connstream.close()
And go back to listening for new client connections.

View file

@ -284,8 +284,38 @@ The :mod:`test.test_support` module defines the following functions:
This will run all tests defined in the named module.
The :mod:`test.test_support` module defines the following classes:
.. function:: catch_warning()
This is a context manager that guards the warnings filter from being
permanently changed and records the data of the last warning that has been
issued.
Use like this::
with catch_warning() as w:
warnings.warn("foo")
assert str(w.message) == "foo"
.. versionadded:: 2.6
.. function:: captured_stdout()
This is a context manager than runs the :keyword:`with` statement body using
a :class:`StringIO.StringIO` object as sys.stdout. That object can be
retrieved using the ``as`` clause of the with statement.
Example use::
with captured_stdout() as s:
print "hello"
assert s.getvalue() == "hello"
.. versionadded:: 2.6
The :mod:`test.test_support` module defines the following classes:
.. class:: TransientResource(exc[, **kwargs])
@ -314,4 +344,3 @@ The :mod:`test.test_support` module defines the following classes:
.. method:: EnvironmentVarGuard.unset(envvar)
Temporarily unset the environment variable ``envvar``.

View file

@ -69,7 +69,7 @@ The :mod:`urllib2` module defines the following functions:
:class:`HTTPRedirectHandler`, :class:`FTPHandler`, :class:`FileHandler`,
:class:`HTTPErrorProcessor`.
If the Python installation has SSL support (:func:`socket.ssl` exists),
If the Python installation has SSL support (i.e., if the :mod:`ssl` module can be imported),
:class:`HTTPSHandler` will also be added.
Beginning in Python 2.3, a :class:`BaseHandler` subclass may also change its

View file

@ -185,15 +185,41 @@ def __init__(self, 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:]
if isinstance(index, slice):
if isinstance(sub, UserString):
sub = sub.data
elif not isinstance(sub, basestring):
sub = str(sub)
start, stop, step = index.indices(len(self.data))
if step == -1:
start, stop = stop+1, start+1
sub = sub[::-1]
elif step != 1:
# XXX(twouters): I guess we should be reimplementing
# the extended slice assignment/deletion algorithm here...
raise TypeError, "invalid step in slicing assignment"
start = min(start, stop)
self.data = self.data[:start] + sub + self.data[stop:]
else:
if index < 0:
index += len(self.data)
if index < 0 or index >= len(self.data): raise IndexError
self.data = self.data[:index] + sub + self.data[index+1:]
def __delitem__(self, index):
if 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:]
if isinstance(index, slice):
start, stop, step = index.indices(len(self.data))
if step == -1:
start, stop = stop+1, start+1
elif step != 1:
# XXX(twouters): see same block in __setitem__
raise TypeError, "invalid step in slicing deletion"
start = min(start, stop)
self.data = self.data[:start] + self.data[stop:]
else:
if index < 0:
index += len(self.data)
if index < 0 or index >= len(self.data): raise IndexError
self.data = self.data[:index] + self.data[index+1:]
def __setslice__(self, start, end, sub):
start = max(start, 0); end = max(end, 0)
if isinstance(sub, UserString):

View file

@ -336,7 +336,7 @@ class CDLL(object):
<obj>['qsort'] -> callable object
Calling the functions releases the Python GIL during the call and
reaquires it afterwards.
reacquires it afterwards.
"""
class _FuncPtr(_CFuncPtr):
_flags_ = _FUNCFLAG_CDECL

View file

@ -21,8 +21,9 @@
]
def _run_code(code, run_globals, init_globals,
mod_name, mod_fname, mod_loader):
def _run_code(code, run_globals, init_globals=None,
mod_name=None, mod_fname=None,
mod_loader=None):
"""Helper for _run_module_code"""
if init_globals is not None:
run_globals.update(init_globals)
@ -33,21 +34,31 @@ def _run_code(code, run_globals, init_globals,
return run_globals
def _run_module_code(code, init_globals=None,
mod_name=None, mod_fname=None,
mod_loader=None, alter_sys=False):
mod_name=None, mod_fname=None,
mod_loader=None):
"""Helper for run_module"""
# Set up the top level namespace dictionary
if alter_sys:
# Modify sys.argv[0] and sys.modules[mod_name]
sys.argv[0] = mod_fname
module = imp.new_module(mod_name)
sys.modules[mod_name] = module
mod_globals = module.__dict__
else:
# Leave the sys module alone
mod_globals = {}
return _run_code(code, mod_globals, init_globals,
mod_name, mod_fname, mod_loader)
temp_module = imp.new_module(mod_name)
mod_globals = temp_module.__dict__
# Modify sys.argv[0] and sys.module[mod_name]
saved_argv0 = sys.argv[0]
restore_module = mod_name in sys.modules
if restore_module:
saved_module = sys.modules[mod_name]
sys.argv[0] = mod_fname
sys.modules[mod_name] = temp_module
try:
_run_code(code, mod_globals, init_globals,
mod_name, mod_fname, mod_loader)
finally:
sys.argv[0] = saved_argv0
if restore_module:
sys.modules[mod_name] = saved_module
else:
del sys.modules[mod_name]
# Copy the globals of the temporary module, as they
# may be cleared when the temporary module goes away
return mod_globals.copy()
# This helper is needed due to a missing component in the PEP 302
@ -60,13 +71,8 @@ def _get_filename(loader, mod_name):
else:
return get_filename(mod_name)
def run_module(mod_name, init_globals=None,
run_name=None, alter_sys=False):
"""Execute a module's code without importing it
Returns the resulting top level namespace dictionary
"""
# Helper to get the loader, code and filename for a module
def _get_module_details(mod_name):
loader = get_loader(mod_name)
if loader is None:
raise ImportError("No module named %s" % mod_name)
@ -77,10 +83,40 @@ def run_module(mod_name, init_globals=None,
if code is None:
raise ImportError("No code object available for %s" % mod_name)
filename = _get_filename(loader, mod_name)
return loader, code, filename
# XXX ncoghlan: Should this be documented and made public?
def _run_module_as_main(mod_name, set_argv0=True):
"""Runs the designated module in the __main__ namespace
These __*__ magic variables will be overwritten:
__file__
__loader__
"""
loader, code, fname = _get_module_details(mod_name)
main_globals = sys.modules["__main__"].__dict__
if set_argv0:
sys.argv[0] = fname
return _run_code(code, main_globals, None,
"__main__", fname, loader)
def run_module(mod_name, init_globals=None,
run_name=None, alter_sys=False):
"""Execute a module's code without importing it
Returns the resulting top level namespace dictionary
"""
loader, code, fname = _get_module_details(mod_name)
if run_name is None:
run_name = mod_name
return _run_module_code(code, init_globals, run_name,
filename, loader, alter_sys)
if alter_sys:
return _run_module_code(code, init_globals, run_name,
fname, loader)
else:
# Leave the sys module alone
return _run_code(code, {}, init_globals,
run_name, fname, loader)
if __name__ == "__main__":
@ -89,4 +125,4 @@ def run_module(mod_name, init_globals=None,
print("No module specified for execution", file=sys.stderr)
else:
del sys.argv[0] # Make the requested module sys.argv[0]
run_module(sys.argv[0], run_name="__main__", alter_sys=True)
_run_module_as_main(sys.argv[0])

View file

@ -65,6 +65,10 @@
__all__.extend(os._get_exports_list(_socket))
if _have_ssl:
__all__.extend(os._get_exports_list(_ssl))
def ssl(sock, keyfile=None, certfile=None):
import ssl as realssl
return realssl.sslwrap_simple(sock, keyfile, certfile)
__all__.append("ssl")
# WSA error codes
if sys.platform.lower().startswith("win"):

253
Lib/ssl.py Normal file
View file

@ -0,0 +1,253 @@
# Wrapper module for _ssl, providing some additional facilities
# implemented in Python. Written by Bill Janssen.
"""\
This module provides some more Pythonic support for SSL.
Object types:
sslsocket -- subtype of socket.socket which does SSL over the socket
Exceptions:
sslerror -- exception raised for I/O errors
Functions:
cert_time_to_seconds -- convert time string used for certificate
notBefore and notAfter functions to integer
seconds past the Epoch (the time values
returned from time.time())
fetch_server_certificate (HOST, PORT) -- fetch the certificate provided
by the server running on HOST at port PORT. No
validation of the certificate is performed.
Integer constants:
SSL_ERROR_ZERO_RETURN
SSL_ERROR_WANT_READ
SSL_ERROR_WANT_WRITE
SSL_ERROR_WANT_X509_LOOKUP
SSL_ERROR_SYSCALL
SSL_ERROR_SSL
SSL_ERROR_WANT_CONNECT
SSL_ERROR_EOF
SSL_ERROR_INVALID_ERROR_CODE
The following group define certificate requirements that one side is
allowing/requiring from the other side:
CERT_NONE - no certificates from the other side are required (or will
be looked at if provided)
CERT_OPTIONAL - certificates are not required, but if provided will be
validated, and if validation fails, the connection will
also fail
CERT_REQUIRED - certificates are required, and will be validated, and
if validation fails, the connection will also fail
The following constants identify various SSL protocol variants:
PROTOCOL_SSLv2
PROTOCOL_SSLv3
PROTOCOL_SSLv23
PROTOCOL_TLSv1
"""
import os, sys
import _ssl # if we can't import it, let the error propagate
from socket import socket
from _ssl import sslerror
from _ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED
from _ssl import PROTOCOL_SSLv2, PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1
# Root certs:
#
# The "ca_certs" argument to sslsocket() expects a file containing one or more
# certificates that are roots of various certificate signing chains. This file
# contains the certificates in PEM format (RFC ) where each certificate is
# encoded in base64 encoding and surrounded with a header and footer:
# -----BEGIN CERTIFICATE-----
# ... (CA certificate in base64 encoding) ...
# -----END CERTIFICATE-----
# The various certificates in the file are just concatenated together:
# -----BEGIN CERTIFICATE-----
# ... (CA certificate in base64 encoding) ...
# -----END CERTIFICATE-----
# -----BEGIN CERTIFICATE-----
# ... (a second CA certificate in base64 encoding) ...
# -----END CERTIFICATE-----
#
# Some "standard" root certificates are available at
#
# http://www.thawte.com/roots/ (for Thawte roots)
# http://www.verisign.com/support/roots.html (for Verisign)
class sslsocket (socket):
def __init__(self, sock, keyfile=None, certfile=None,
server_side=False, cert_reqs=CERT_NONE,
ssl_version=PROTOCOL_SSLv23, ca_certs=None):
socket.__init__(self, _sock=sock._sock)
if certfile and not keyfile:
keyfile = certfile
if server_side:
self._sslobj = _ssl.sslwrap(self._sock, 1, keyfile, certfile,
cert_reqs, ssl_version, ca_certs)
else:
# see if it's connected
try:
socket.getpeername(self)
except:
# no, no connection yet
self._sslobj = None
else:
# yes, create the SSL object
self._sslobj = _ssl.sslwrap(self._sock, 0, keyfile, certfile,
cert_reqs, ssl_version, ca_certs)
self.keyfile = keyfile
self.certfile = certfile
self.cert_reqs = cert_reqs
self.ssl_version = ssl_version
self.ca_certs = ca_certs
def read(self, len=1024):
return self._sslobj.read(len)
def write(self, data):
return self._sslobj.write(data)
def getpeercert(self):
return self._sslobj.peer_certificate()
def send (self, data, flags=0):
if flags != 0:
raise ValueError(
"non-zero flags not allowed in calls to send() on %s" %
self.__class__)
return self._sslobj.write(data)
def send_to (self, data, addr, flags=0):
raise ValueError("send_to not allowed on instances of %s" %
self.__class__)
def sendall (self, data, flags=0):
if flags != 0:
raise ValueError(
"non-zero flags not allowed in calls to sendall() on %s" %
self.__class__)
return self._sslobj.write(data)
def recv (self, buflen=1024, flags=0):
if flags != 0:
raise ValueError(
"non-zero flags not allowed in calls to sendall() on %s" %
self.__class__)
return self._sslobj.read(data, buflen)
def recv_from (self, addr, buflen=1024, flags=0):
raise ValueError("recv_from not allowed on instances of %s" %
self.__class__)
def shutdown(self):
if self._sslobj:
self._sslobj.shutdown()
self._sslobj = None
else:
socket.shutdown(self)
def close(self):
if self._sslobj:
self.shutdown()
else:
socket.close(self)
def connect(self, addr):
# Here we assume that the socket is client-side, and not
# connected at the time of the call. We connect it, then wrap it.
if self._sslobj or (self.getsockname()[1] != 0):
raise ValueError("attempt to connect already-connected sslsocket!")
socket.connect(self, addr)
self._sslobj = _ssl.sslwrap(self._sock, 0, self.keyfile, self.certfile,
self.cert_reqs, self.ssl_version,
self.ca_certs)
def accept(self):
raise ValueError("accept() not supported on an sslsocket")
# some utility functions
def cert_time_to_seconds(cert_time):
import time
return time.mktime(time.strptime(cert_time, "%b %d %H:%M:%S %Y GMT"))
# a replacement for the old socket.ssl function
def sslwrap_simple (sock, keyfile=None, certfile=None):
return _ssl.sslwrap(sock._sock, 0, keyfile, certfile, CERT_NONE,
PROTOCOL_SSLv23, None)
# fetch the certificate that the server is providing in PEM form
def fetch_server_certificate (host, port):
import re, tempfile, os
def subproc(cmd):
from subprocess import Popen, PIPE, STDOUT
proc = Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True)
status = proc.wait()
output = proc.stdout.read()
return status, output
def strip_to_x509_cert(certfile_contents, outfile=None):
m = re.search(r"^([-]+BEGIN CERTIFICATE[-]+[\r]*\n"
r".*[\r]*^[-]+END CERTIFICATE[-]+)$",
certfile_contents, re.MULTILINE | re.DOTALL)
if not m:
return None
else:
tn = tempfile.mktemp()
fp = open(tn, "w")
fp.write(m.group(1) + "\n")
fp.close()
try:
tn2 = (outfile or tempfile.mktemp())
status, output = subproc(r'openssl x509 -in "%s" -out "%s"' %
(tn, tn2))
if status != 0:
raise OperationError(status, tsig, output)
fp = open(tn2, 'rb')
data = fp.read()
fp.close()
os.unlink(tn2)
return data
finally:
os.unlink(tn)
if sys.platform.startswith("win"):
tfile = tempfile.mktemp()
fp = open(tfile, "w")
fp.write("quit\n")
fp.close()
try:
status, output = subproc(
'openssl s_client -connect "%s:%s" -showcerts < "%s"' %
(host, port, tfile))
finally:
os.unlink(tfile)
else:
status, output = subproc(
'openssl s_client -connect "%s:%s" -showcerts < /dev/null' %
(host, port))
if status != 0:
raise OSError(status)
certtext = strip_to_x509_cert(output)
if not certtext:
raise ValueError("Invalid response received from server at %s:%s" %
(host, port))
return certtext

View file

@ -1508,7 +1508,7 @@ def __init__(self, name=None, mode="r", fileobj=None, format=None,
if hasattr(fileobj, "mode"):
self._mode = fileobj.mode
self._extfileobj = True
self.name = os.path.abspath(name)
self.name = os.path.abspath(name) if name else None
self.fileobj = fileobj
# Init attributes.

32
Lib/test/keycert.pem Normal file
View file

@ -0,0 +1,32 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXwIBAAKBgQC8ddrhm+LutBvjYcQlnH21PPIseJ1JVG2HMmN2CmZk2YukO+9L
opdJhTvbGfEj0DQs1IE8M+kTUyOmuKfVrFMKwtVeCJphrAnhoz7TYOuLBSqt7lVH
fhi/VwovESJlaBOp+WMnfhcduPEYHYx/6cnVapIkZnLt30zu2um+DzA9jQIDAQAB
AoGBAK0FZpaKj6WnJZN0RqhhK+ggtBWwBnc0U/ozgKz2j1s3fsShYeiGtW6CK5nU
D1dZ5wzhbGThI7LiOXDvRucc9n7vUgi0alqPQ/PFodPxAN/eEYkmXQ7W2k7zwsDA
IUK0KUhktQbLu8qF/m8qM86ba9y9/9YkXuQbZ3COl5ahTZrhAkEA301P08RKv3KM
oXnGU2UHTuJ1MAD2hOrPxjD4/wxA/39EWG9bZczbJyggB4RHu0I3NOSFjAm3HQm0
ANOu5QK9owJBANgOeLfNNcF4pp+UikRFqxk5hULqRAWzVxVrWe85FlPm0VVmHbb/
loif7mqjU8o1jTd/LM7RD9f2usZyE2psaw8CQQCNLhkpX3KO5kKJmS9N7JMZSc4j
oog58yeYO8BBqKKzpug0LXuQultYv2K4veaIO04iL9VLe5z9S/Q1jaCHBBuXAkEA
z8gjGoi1AOp6PBBLZNsncCvcV/0aC+1se4HxTNo2+duKSDnbq+ljqOM+E7odU+Nq
ewvIWOG//e8fssd0mq3HywJBAJ8l/c8GVmrpFTx8r/nZ2Pyyjt3dH1widooDXYSV
q6Gbf41Llo5sYAtmxdndTLASuHKecacTgZVhy0FryZpLKrU=
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIICpzCCAhCgAwIBAgIJAP+qStv1cIGNMA0GCSqGSIb3DQEBBQUAMIGJMQswCQYD
VQQGEwJVUzERMA8GA1UECBMIRGVsYXdhcmUxEzARBgNVBAcTCldpbG1pbmd0b24x
IzAhBgNVBAoTGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9uMQwwCgYDVQQLEwNT
U0wxHzAdBgNVBAMTFnNvbWVtYWNoaW5lLnB5dGhvbi5vcmcwHhcNMDcwODI3MTY1
NDUwWhcNMTMwMjE2MTY1NDUwWjCBiTELMAkGA1UEBhMCVVMxETAPBgNVBAgTCERl
bGF3YXJlMRMwEQYDVQQHEwpXaWxtaW5ndG9uMSMwIQYDVQQKExpQeXRob24gU29m
dHdhcmUgRm91bmRhdGlvbjEMMAoGA1UECxMDU1NMMR8wHQYDVQQDExZzb21lbWFj
aGluZS5weXRob24ub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8ddrh
m+LutBvjYcQlnH21PPIseJ1JVG2HMmN2CmZk2YukO+9LopdJhTvbGfEj0DQs1IE8
M+kTUyOmuKfVrFMKwtVeCJphrAnhoz7TYOuLBSqt7lVHfhi/VwovESJlaBOp+WMn
fhcduPEYHYx/6cnVapIkZnLt30zu2um+DzA9jQIDAQABoxUwEzARBglghkgBhvhC
AQEEBAMCBkAwDQYJKoZIhvcNAQEFBQADgYEAF4Q5BVqmCOLv1n8je/Jw9K669VXb
08hyGzQhkemEBYQd6fzQ9A/1ZzHkJKb1P6yreOLSEh4KcxYPyrLRC1ll8nr5OlCx
CMhKkTnR6qBsdNV0XtdU2+N25hqW+Ma4ZeqsN/iiJVCGNOZGnvQuvCAGWF8+J/f/
iHkC6gGdBJhogs4=
-----END CERTIFICATE-----

View file

@ -179,8 +179,10 @@ def test_setslice(self):
self.assertEqual(a, self.type2test(range(10)))
self.assertRaises(TypeError, a.__setslice__, 0, 1, 5)
self.assertRaises(TypeError, a.__setitem__, slice(0, 1, 5))
self.assertRaises(TypeError, a.__setslice__)
self.assertRaises(TypeError, a.__setitem__)
def test_delslice(self):
a = self.type2test([0, 1])

View file

@ -1,64 +0,0 @@
test_class
__init__: ()
__add__: (1,)
__radd__: (1,)
__sub__: (1,)
__rsub__: (1,)
__mul__: (1,)
__rmul__: (1,)
__truediv__: (1,)
__rtruediv__: (1,)
__mod__: (1,)
__rmod__: (1,)
__divmod__: (1,)
__rdivmod__: (1,)
__pow__: (1,)
__rpow__: (1,)
__rshift__: (1,)
__rrshift__: (1,)
__lshift__: (1,)
__rlshift__: (1,)
__and__: (1,)
__rand__: (1,)
__or__: (1,)
__ror__: (1,)
__xor__: (1,)
__rxor__: (1,)
__contains__: (1,)
__getitem__: (1,)
__setitem__: (1, 1)
__delitem__: (1,)
__getslice__: (0, 42)
__setslice__: (0, 42, 'The Answer')
__delslice__: (0, 42)
__getitem__: (slice(2, 1024, 10),)
__setitem__: (slice(2, 1024, 10), 'A lot')
__delitem__: (slice(2, 1024, 10),)
__getitem__: ((slice(None, 42, None), Ellipsis, slice(None, 24, None), 24, 100),)
__setitem__: ((slice(None, 42, None), Ellipsis, slice(None, 24, None), 24, 100), 'Strange')
__delitem__: ((slice(None, 42, None), Ellipsis, slice(None, 24, None), 24, 100),)
__getitem__: (slice(None, 42, None),)
__setitem__: (slice(None, 42, None), 'The Answer')
__delitem__: (slice(None, 42, None),)
__neg__: ()
__pos__: ()
__abs__: ()
__int__: ()
__int__: ()
__float__: ()
__index__: ()
__hash__: ()
__repr__: ()
__str__: ()
__eq__: (1,)
__lt__: (1,)
__gt__: (1,)
__ne__: (1,)
__eq__: (1,)
__gt__: (1,)
__lt__: (1,)
__ne__: (1,)
__del__: ()
__getattr__: ('spam',)
__setattr__: ('eggs', 'spam, spam, spam and ham')
__delattr__: ('cardinal',)

View file

@ -1,4 +0,0 @@
test_frozen
Hello world...
Hello world...
Hello world...

View file

@ -1,2 +0,0 @@
test_ossaudiodev
playing test sound file (expected running time: 2.93 sec)

View file

@ -1,2 +0,0 @@
test_signal
starting pause() loop...

View file

@ -1,3 +0,0 @@
test_winreg
Local registry tests worked
Remote registry calls can be tested using 'test_winreg.py --remote \\machine_name'

View file

@ -935,7 +935,6 @@ def test_subscript(self):
self.checkequal('abc', 'abc', '__getitem__', slice(0, 1000))
self.checkequal('a', 'abc', '__getitem__', slice(0, 1))
self.checkequal('', 'abc', '__getitem__', slice(0, 0))
# FIXME What about negative indices? This is handled differently by [] and __getitem__(slice)
self.checkraises(TypeError, 'abc', '__getitem__', 'def')
@ -949,10 +948,21 @@ def test_slice(self):
self.checkequal('', 'abc', '__getslice__', 1000, 1000)
self.checkequal('', 'abc', '__getslice__', 2000, 1000)
self.checkequal('', 'abc', '__getslice__', 2, 1)
# FIXME What about negative indizes? This is handled differently by [] and __getslice__
self.checkraises(TypeError, 'abc', '__getslice__', 'def')
def test_extended_getslice(self):
# Test extended slicing by comparing with list slicing.
s = string.ascii_letters + string.digits
indices = (0, None, 1, 3, 41, -1, -2, -37)
for start in indices:
for stop in indices:
# Skip step 0 (invalid)
for step in indices[1:]:
L = list(s)[start:stop:step]
self.checkequal("".join(L), s, '__getitem__',
slice(start, stop, step))
def test_mul(self):
self.checkequal('', 'abc', '__mul__', -1)
self.checkequal('', 'abc', '__mul__', 0)

View file

@ -468,6 +468,18 @@ def test_getslice(self):
array.array(self.typecode)
)
def test_extended_getslice(self):
# Test extended slicing by comparing with list slicing
# (Assumes list conversion works correctly, too)
a = array.array(self.typecode, self.example)
indices = (0, None, 1, 3, 19, 100, -1, -2, -31, -100)
for start in indices:
for stop in indices:
# Everything except the initial 0 (invalid step)
for step in indices[1:]:
self.assertEqual(list(a[start:stop:step]),
list(a)[start:stop:step])
def test_setslice(self):
a = array.array(self.typecode, self.example)
a[:1] = a
@ -551,12 +563,34 @@ def test_setslice(self):
a = array.array(self.typecode, self.example)
self.assertRaises(TypeError, a.__setslice__, 0, 0, None)
self.assertRaises(TypeError, a.__setitem__, slice(0, 0), None)
self.assertRaises(TypeError, a.__setitem__, slice(0, 1), None)
b = array.array(self.badtypecode())
self.assertRaises(TypeError, a.__setslice__, 0, 0, b)
self.assertRaises(TypeError, a.__setitem__, slice(0, 0), b)
self.assertRaises(TypeError, a.__setitem__, slice(0, 1), b)
def test_extended_set_del_slice(self):
indices = (0, None, 1, 3, 19, 100, -1, -2, -31, -100)
for start in indices:
for stop in indices:
# Everything except the initial 0 (invalid step)
for step in indices[1:]:
a = array.array(self.typecode, self.example)
L = list(a)
# Make sure we have a slice of exactly the right length,
# but with (hopefully) different data.
data = L[start:stop:step]
data.reverse()
L[start:stop:step] = data
a[start:stop:step] = array.array(self.typecode, data)
self.assertEquals(a, array.array(self.typecode, L))
del L[start:stop:step]
del a[start:stop:step]
self.assertEquals(a, array.array(self.typecode, L))
def test_index(self):
example = 2*self.example
a = array.array(self.typecode, example)

View file

@ -37,6 +37,18 @@ def test_comparison(self):
self.failIf(a == b)
self.assertRaises(TypeError, lambda: a < b)
def test_extended_getslice(self):
# Test extended slicing by comparing with list slicing.
s = bytes(range(255, -1, -1))
b = buffer(s)
indices = (0, None, 1, 3, 19, 300, -1, -2, -31, -300)
for start in indices:
for stop in indices:
# Skip step 0 (invalid)
for step in indices[1:]:
self.assertEqual(b[start:stop:step],
s[start:stop:step])
def test_main():
test_support.run_unittest(BufferTests)

View file

@ -1,6 +1,9 @@
"Test the functionality of Python classes implementing operators."
from test.test_support import TestFailed
import unittest
import sys
from test import test_support
testmeths = [
@ -53,340 +56,540 @@
# "str",
# "repr",
# "int",
# "long",
# "float",
# "oct",
# "hex",
# These are separate because they can influence the test of other methods.
# "getattr",
# "setattr",
# "delattr",
class AllTests:
def __hash__(self, *args):
print("__hash__:", args)
return hash(id(self))
callLst = []
def trackCall(f):
def track(*args, **kwargs):
callLst.append((f.__name__, args))
return f(*args, **kwargs)
return track
def __str__(self, *args):
print("__str__:", args)
return "AllTests"
statictests = """
@trackCall
def __hash__(self, *args):
return hash(id(self))
def __repr__(self, *args):
print("__repr__:", args)
return "AllTests"
@trackCall
def __str__(self, *args):
return "AllTests"
def __int__(self, *args):
print("__int__:", args)
return 1
@trackCall
def __repr__(self, *args):
return "AllTests"
def __index__(self, *args):
print("__index__:", args)
return 1
@trackCall
def __int__(self, *args):
return 1
def __float__(self, *args):
print("__float__:", args)
return 1.0
@trackCall
def __index__(self, *args):
return 1
def __cmp__(self, *args):
print("__cmp__:", args)
return 0
@trackCall
def __float__(self, *args):
return 1.0
def __eq__(self, *args):
print("__eq__:", args)
return True
@trackCall
def __cmp__(self, *args):
return 0
def __ne__(self, *args):
print("__ne__:", args)
return False
@trackCall
def __eq__(self, *args):
return True
def __lt__(self, *args):
print("__lt__:", args)
return False
@trackCall
def __ne__(self, *args):
return False
def __le__(self, *args):
print("__le__:", args)
return True
@trackCall
def __lt__(self, *args):
return False
def __gt__(self, *args):
print("__gt__:", args)
return False
@trackCall
def __le__(self, *args):
return True
def __ge__(self, *args):
print("__ge__:", args)
return True
@trackCall
def __gt__(self, *args):
return False
def __del__(self, *args):
print("__del__:", args)
@trackCall
def __ge__(self, *args):
return True
"""
# Synthesize AllTests methods from the names in testmeths.
# Synthesize all the other AllTests methods from the names in testmeths.
method_template = """\
def __%(method)s__(self, *args):
print("__%(method)s__:", args)
@trackCall
def __%s__(self, *args):
pass
"""
d = {}
exec(statictests, globals(), d)
for method in testmeths:
exec(method_template % locals(), d)
for k in d:
setattr(AllTests, k, d[k])
del d, k
del method, method_template
exec(method_template % method, globals(), d)
AllTests = type("AllTests", (object,), d)
del d, statictests, method, method_template
# this also tests __init__ of course.
testme = AllTests()
class ClassTests(unittest.TestCase):
def setUp(self):
callLst[:] = []
# Binary operations
def assertCallStack(self, expected_calls):
actualCallList = callLst[:] # need to copy because the comparison below will add
# additional calls to callLst
if expected_calls != actualCallList:
self.fail("Expected call list:\n %s\ndoes not match actual call list\n %s" %
(expected_calls, actualCallList))
testme + 1
1 + testme
def testInit(self):
foo = AllTests()
self.assertCallStack([("__init__", (foo,))])
testme - 1
1 - testme
def testBinaryOps(self):
testme = AllTests()
# Binary operations
testme * 1
1 * testme
callLst[:] = []
testme + 1
self.assertCallStack([("__add__", (testme, 1))])
testme / 1
1 / testme
callLst[:] = []
1 + testme
self.assertCallStack([("__radd__", (testme, 1))])
testme % 1
1 % testme
callLst[:] = []
testme - 1
self.assertCallStack([("__sub__", (testme, 1))])
divmod(testme,1)
divmod(1, testme)
callLst[:] = []
1 - testme
self.assertCallStack([("__rsub__", (testme, 1))])
testme ** 1
1 ** testme
callLst[:] = []
testme * 1
self.assertCallStack([("__mul__", (testme, 1))])
testme >> 1
1 >> testme
callLst[:] = []
1 * testme
self.assertCallStack([("__rmul__", (testme, 1))])
testme << 1
1 << testme
testme & 1
1 & testme
testme | 1
1 | testme
testme ^ 1
1 ^ testme
if 1/2 == 0:
callLst[:] = []
testme / 1
self.assertCallStack([("__div__", (testme, 1))])
# List/dict operations
callLst[:] = []
1 / testme
self.assertCallStack([("__rdiv__", (testme, 1))])
class Empty: pass
callLst[:] = []
testme % 1
self.assertCallStack([("__mod__", (testme, 1))])
try:
1 in Empty()
print('failed, should have raised TypeError')
except TypeError:
pass
1 in testme
testme[1]
testme[1] = 1
del testme[1]
testme[:42]
testme[:42] = "The Answer"
del testme[:42]
testme[2:1024:10]
testme[2:1024:10] = "A lot"
del testme[2:1024:10]
testme[:42, ..., :24:, 24, 100]
testme[:42, ..., :24:, 24, 100] = "Strange"
del testme[:42, ..., :24:, 24, 100]
callLst[:] = []
1 % testme
self.assertCallStack([("__rmod__", (testme, 1))])
# Now remove the slice hooks to see if converting normal slices to slice
# object works.
callLst[:] = []
divmod(testme,1)
self.assertCallStack([("__divmod__", (testme, 1))])
del AllTests.__getslice__
del AllTests.__setslice__
del AllTests.__delslice__
callLst[:] = []
divmod(1, testme)
self.assertCallStack([("__rdivmod__", (testme, 1))])
import sys
if sys.platform[:4] != 'java':
testme[:42]
testme[:42] = "The Answer"
del testme[:42]
else:
# This works under Jython, but the actual slice values are
# different.
print("__getitem__: (slice(0, 42, None),)")
print("__setitem__: (slice(0, 42, None), 'The Answer')")
print("__delitem__: (slice(0, 42, None),)")
callLst[:] = []
testme ** 1
self.assertCallStack([("__pow__", (testme, 1))])
# Unary operations
callLst[:] = []
1 ** testme
self.assertCallStack([("__rpow__", (testme, 1))])
-testme
+testme
abs(testme)
int(testme)
int(testme)
float(testme)
oct(testme)
callLst[:] = []
testme >> 1
self.assertCallStack([("__rshift__", (testme, 1))])
# And the rest...
callLst[:] = []
1 >> testme
self.assertCallStack([("__rrshift__", (testme, 1))])
hash(testme)
repr(testme)
str(testme)
callLst[:] = []
testme << 1
self.assertCallStack([("__lshift__", (testme, 1))])
testme == 1
testme < 1
testme > 1
testme != 1
1 == testme
1 < testme
1 > testme
1 != testme
callLst[:] = []
1 << testme
self.assertCallStack([("__rlshift__", (testme, 1))])
# This test has to be last (duh.)
callLst[:] = []
testme & 1
self.assertCallStack([("__and__", (testme, 1))])
del testme
if sys.platform[:4] == 'java':
import java
java.lang.System.gc()
callLst[:] = []
1 & testme
self.assertCallStack([("__rand__", (testme, 1))])
# Interfering tests
callLst[:] = []
testme | 1
self.assertCallStack([("__or__", (testme, 1))])
class ExtraTests:
def __getattr__(self, *args):
print("__getattr__:", args)
return "SomeVal"
callLst[:] = []
1 | testme
self.assertCallStack([("__ror__", (testme, 1))])
def __setattr__(self, *args):
print("__setattr__:", args)
callLst[:] = []
testme ^ 1
self.assertCallStack([("__xor__", (testme, 1))])
def __delattr__(self, *args):
print("__delattr__:", args)
callLst[:] = []
1 ^ testme
self.assertCallStack([("__rxor__", (testme, 1))])
testme = ExtraTests()
testme.spam
testme.eggs = "spam, spam, spam and ham"
del testme.cardinal
def testListAndDictOps(self):
testme = AllTests()
# List/dict operations
class Empty: pass
try:
1 in Empty()
self.fail('failed, should have raised TypeError')
except TypeError:
pass
callLst[:] = []
1 in testme
self.assertCallStack([('__contains__', (testme, 1))])
callLst[:] = []
testme[1]
self.assertCallStack([('__getitem__', (testme, 1))])
callLst[:] = []
testme[1] = 1
self.assertCallStack([('__setitem__', (testme, 1, 1))])
callLst[:] = []
del testme[1]
self.assertCallStack([('__delitem__', (testme, 1))])
callLst[:] = []
testme[:42]
self.assertCallStack([('__getslice__', (testme, 0, 42))])
callLst[:] = []
testme[:42] = "The Answer"
self.assertCallStack([('__setslice__', (testme, 0, 42, "The Answer"))])
callLst[:] = []
del testme[:42]
self.assertCallStack([('__delslice__', (testme, 0, 42))])
callLst[:] = []
testme[2:1024:10]
self.assertCallStack([('__getitem__', (testme, slice(2, 1024, 10)))])
callLst[:] = []
testme[2:1024:10] = "A lot"
self.assertCallStack([('__setitem__', (testme, slice(2, 1024, 10),
"A lot"))])
callLst[:] = []
del testme[2:1024:10]
self.assertCallStack([('__delitem__', (testme, slice(2, 1024, 10)))])
callLst[:] = []
testme[:42, ..., :24:, 24, 100]
self.assertCallStack([('__getitem__', (testme, (slice(None, 42, None),
Ellipsis,
slice(None, 24, None),
24, 100)))])
callLst[:] = []
testme[:42, ..., :24:, 24, 100] = "Strange"
self.assertCallStack([('__setitem__', (testme, (slice(None, 42, None),
Ellipsis,
slice(None, 24, None),
24, 100), "Strange"))])
callLst[:] = []
del testme[:42, ..., :24:, 24, 100]
self.assertCallStack([('__delitem__', (testme, (slice(None, 42, None),
Ellipsis,
slice(None, 24, None),
24, 100)))])
# Now remove the slice hooks to see if converting normal slices to
# slice object works.
getslice = AllTests.__getslice__
del AllTests.__getslice__
setslice = AllTests.__setslice__
del AllTests.__setslice__
delslice = AllTests.__delslice__
del AllTests.__delslice__
# XXX when using new-style classes the slice testme[:42] produces
# slice(None, 42, None) instead of slice(0, 42, None). py3k will have
# to change this test.
callLst[:] = []
testme[0:42]
self.assertCallStack([('__getitem__', (testme, slice(0, 42, None)))])
callLst[:] = []
testme[:42] = "The Answer"
self.assertCallStack([('__setitem__', (testme, slice(None, 42, None),
"The Answer"))])
callLst[:] = []
del testme[0:42]
self.assertCallStack([('__delitem__', (testme, slice(0, 42, None)))])
# Restore the slice methods, or the tests will fail with regrtest -R.
AllTests.__getslice__ = getslice
AllTests.__setslice__ = setslice
AllTests.__delslice__ = delslice
# return values of some method are type-checked
class BadTypeClass:
def __int__(self):
return None
__float__ = __int__
__str__ = __int__
__repr__ = __int__
def testUnaryOps(self):
testme = AllTests()
def check_exc(stmt, exception):
"""Raise TestFailed if executing 'stmt' does not raise 'exception'
"""
try:
exec(stmt)
except exception:
pass
else:
raise TestFailed, "%s should raise %s" % (stmt, exception)
check_exc("int(BadTypeClass())", TypeError)
check_exc("float(BadTypeClass())", TypeError)
check_exc("str(BadTypeClass())", TypeError)
check_exc("repr(BadTypeClass())", TypeError)
check_exc("oct(BadTypeClass())", TypeError)
check_exc("hex(BadTypeClass())", TypeError)
# Test correct errors from hash() on objects with comparisons but no __hash__
class C0:
pass
hash(C0()) # This should work; the next two should raise TypeError
class C1:
def __cmp__(self, other): return 0
check_exc("hash(C1())", TypeError)
class C2:
def __eq__(self, other): return 1
check_exc("hash(C2())", TypeError)
# Test for SF bug 532646
class A:
pass
A.__call__ = A()
a = A()
try:
a() # This should not segfault
except RuntimeError:
pass
else:
raise TestFailed, "how could this not have overflowed the stack?"
callLst[:] = []
-testme
self.assertCallStack([('__neg__', (testme,))])
callLst[:] = []
+testme
self.assertCallStack([('__pos__', (testme,))])
callLst[:] = []
abs(testme)
self.assertCallStack([('__abs__', (testme,))])
callLst[:] = []
int(testme)
self.assertCallStack([('__int__', (testme,))])
callLst[:] = []
float(testme)
self.assertCallStack([('__float__', (testme,))])
callLst[:] = []
oct(testme)
self.assertCallStack([('__index__', (testme,))])
callLst[:] = []
hex(testme)
self.assertCallStack([('__index__', (testme,))])
# Tests for exceptions raised in instance_getattr2().
def testMisc(self):
testme = AllTests()
def booh(self):
raise AttributeError, "booh"
callLst[:] = []
hash(testme)
self.assertCallStack([('__hash__', (testme,))])
class A:
a = property(booh)
try:
A().a # Raised AttributeError: A instance has no attribute 'a'
except AttributeError as x:
if str(x) != "booh":
print("attribute error for A().a got masked:", str(x))
callLst[:] = []
repr(testme)
self.assertCallStack([('__repr__', (testme,))])
class E:
__eq__ = property(booh)
E() == E() # In debug mode, caused a C-level assert() to fail
callLst[:] = []
str(testme)
self.assertCallStack([('__str__', (testme,))])
class I:
__init__ = property(booh)
try:
I() # In debug mode, printed XXX undetected error and raises AttributeError
except AttributeError as x:
pass
else:
print("attribute error for I.__init__ got masked")
callLst[:] = []
testme == 1
self.assertCallStack([('__eq__', (testme, 1))])
callLst[:] = []
testme < 1
self.assertCallStack([('__lt__', (testme, 1))])
callLst[:] = []
testme > 1
self.assertCallStack([('__gt__', (testme, 1))])
callLst[:] = []
testme != 1
self.assertCallStack([('__ne__', (testme, 1))])
callLst[:] = []
1 == testme
self.assertCallStack([('__eq__', (1, testme))])
callLst[:] = []
1 < testme
self.assertCallStack([('__gt__', (1, testme))])
callLst[:] = []
1 > testme
self.assertCallStack([('__lt__', (1, testme))])
callLst[:] = []
1 != testme
self.assertCallStack([('__ne__', (1, testme))])
# Test comparison and hash of methods
class A:
def __init__(self, x):
self.x = x
def f(self):
pass
def g(self):
pass
def __eq__(self, other):
return self.x == other.x
def __hash__(self):
return self.x
class B(A):
pass
def testGetSetAndDel(self):
# Interfering tests
class ExtraTests(AllTests):
@trackCall
def __getattr__(self, *args):
return "SomeVal"
a1 = A(1)
a2 = A(2)
assert a1.f == a1.f
assert a1.f != a2.f
assert a1.f != a1.g
assert a1.f == A(1).f
assert hash(a1.f) == hash(a1.f)
assert hash(a1.f) == hash(A(1).f)
@trackCall
def __setattr__(self, *args):
pass
assert A.f != a1.f
assert A.f != A.g
assert B.f == A.f
assert hash(B.f) == hash(A.f)
@trackCall
def __delattr__(self, *args):
pass
# the following triggers a SystemError in 2.4
a = A(hash(A.f.im_func)^(-1))
hash(a.f)
testme = ExtraTests()
callLst[:] = []
testme.spam
self.assertCallStack([('__getattr__', (testme, "spam"))])
callLst[:] = []
testme.eggs = "spam, spam, spam and ham"
self.assertCallStack([('__setattr__', (testme, "eggs",
"spam, spam, spam and ham"))])
callLst[:] = []
del testme.cardinal
self.assertCallStack([('__delattr__', (testme, "cardinal"))])
def testDel(self):
x = []
class DelTest:
def __del__(self):
x.append("crab people, crab people")
testme = DelTest()
del testme
import gc
gc.collect()
self.assertEquals(["crab people, crab people"], x)
def testBadTypeReturned(self):
# return values of some method are type-checked
class BadTypeClass:
def __int__(self):
return None
__float__ = __int__
__str__ = __int__
__repr__ = __int__
__oct__ = __int__
__hex__ = __int__
for f in [int, float, str, repr, oct, hex]:
self.assertRaises(TypeError, f, BadTypeClass())
def testHashStuff(self):
# Test correct errors from hash() on objects with comparisons but
# no __hash__
class C0:
pass
hash(C0()) # This should work; the next two should raise TypeError
class C1:
def __cmp__(self, other): return 0
self.assertRaises(TypeError, hash, C1())
class C2:
def __eq__(self, other): return 1
self.assertRaises(TypeError, hash, C2())
def testSFBug532646(self):
# Test for SF bug 532646
class A:
pass
A.__call__ = A()
a = A()
try:
a() # This should not segfault
except RuntimeError:
pass
else:
self.fail("Failed to raise RuntimeError")
def testForExceptionsRaisedInInstanceGetattr2(self):
# Tests for exceptions raised in instance_getattr2().
def booh(self):
raise AttributeError("booh")
class A:
a = property(booh)
try:
A().a # Raised AttributeError: A instance has no attribute 'a'
except AttributeError as x:
if str(x) != "booh":
self.fail("attribute error for A().a got masked: %s" % x)
class E:
__eq__ = property(booh)
E() == E() # In debug mode, caused a C-level assert() to fail
class I:
__init__ = property(booh)
try:
# In debug mode, printed XXX undetected error and
# raises AttributeError
I()
except AttributeError as x:
pass
else:
self.fail("attribute error for I.__init__ got masked")
def testHashComparisonOfMethods(self):
# Test comparison and hash of methods
class A:
def __init__(self, x):
self.x = x
def f(self):
pass
def g(self):
pass
def __eq__(self, other):
return self.x == other.x
def __hash__(self):
return self.x
class B(A):
pass
a1 = A(1)
a2 = A(2)
self.assertEquals(a1.f, a1.f)
self.assertNotEquals(a1.f, a2.f)
self.assertNotEquals(a1.f, a1.g)
self.assertEquals(a1.f, A(1).f)
self.assertEquals(hash(a1.f), hash(a1.f))
self.assertEquals(hash(a1.f), hash(A(1).f))
self.assertNotEquals(A.f, a1.f)
self.assertNotEquals(A.f, A.g)
self.assertEquals(B.f, A.f)
self.assertEquals(hash(B.f), hash(A.f))
# the following triggers a SystemError in 2.4
a = A(hash(A.f.im_func)^(-1))
hash(a.f)
def test_main():
test_support.run_unittest(ClassTests)
if __name__=='__main__':
test_main()

View file

@ -3,18 +3,25 @@
import sys
import subprocess
def _spawn_python(*args):
cmd_line = [sys.executable]
cmd_line.extend(args)
return subprocess.Popen(cmd_line, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
def _kill_python(p):
p.stdin.close()
data = p.stdout.read()
p.stdout.close()
# try to cleanup the child so we don't appear to leak when running
# with regrtest -R. This should be a no-op on Windows.
subprocess._cleanup()
return data
class CmdLineTest(unittest.TestCase):
def start_python(self, cmd_line):
cmd = '"%s" %s' % (sys.executable, cmd_line)
p = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
p.stdin.close()
data = p.stdout.read()
p.stdout.close()
# try to cleanup the child so we don't appear to leak when running
# with regrtest -R. This should be a no-op on Windows.
subprocess._cleanup()
return data
def start_python(self, *args):
p = _spawn_python(*args)
return _kill_python(p)
def exit_code(self, *args):
cmd_line = [sys.executable]
@ -72,6 +79,17 @@ def test_run_module(self):
self.exit_code('-m', 'timeit', '-n', '1'),
0)
def test_run_module_bug1764407(self):
# -m and -i need to play well together
# Runs the timeit module and checks the __main__
# namespace has been populated appropriately
p = _spawn_python('-i', '-m', 'timeit', '-n', '1')
p.stdin.write('Timer\n')
p.stdin.write('exit()\n')
data = _kill_python(p)
self.assertTrue(data.find(b'1 loop') != -1)
self.assertTrue(data.find(b'__main__.Timer') != -1)
def test_run_code(self):
# Test expected operation of the '-c' switch
# Switch needs an argument

View file

@ -1,27 +1,40 @@
# Test the frozen module defined in frozen.c.
from __future__ import with_statement
from test.test_support import TestFailed
from test.test_support import captured_stdout, run_unittest
import unittest
import sys, os
try:
import __hello__
except ImportError as x:
raise TestFailed, "import __hello__ failed:" + str(x)
class FrozenTests(unittest.TestCase):
def test_frozen(self):
try:
import __phello__
except ImportError as x:
raise TestFailed, "import __phello__ failed:" + str(x)
with captured_stdout() as stdout:
try:
import __hello__
except ImportError as x:
self.fail("import __hello__ failed:" + str(x))
try:
import __phello__.spam
except ImportError as x:
raise TestFailed, "import __phello__.spam failed:" + str(x)
try:
import __phello__
except ImportError as x:
self.fail("import __phello__ failed:" + str(x))
if sys.platform != "mac": # On the Mac this import does succeed.
try:
import __phello__.foo
except ImportError:
pass
else:
raise TestFailed, "import __phello__.foo should have failed"
try:
import __phello__.spam
except ImportError as x:
self.fail("import __phello__.spam failed:" + str(x))
if sys.platform != "mac": # On the Mac this import does succeed.
try:
import __phello__.foo
except ImportError:
pass
else:
self.fail("import __phello__.foo should have failed")
self.assertEquals(stdout.getvalue(),
'Hello world...\nHello world...\nHello world...\n')
def test_main():
run_unittest(FrozenTests)

View file

@ -305,6 +305,40 @@ def test_anonymous(self):
m[x] = b
self.assertEqual(m[x], b)
def test_extended_getslice(self):
# Test extended slicing by comparing with list slicing.
s = bytes(reversed(range(256)))
m = mmap.mmap(-1, len(s))
m[:] = s
self.assertEqual(m[:], s)
indices = (0, None, 1, 3, 19, 300, -1, -2, -31, -300)
for start in indices:
for stop in indices:
# Skip step 0 (invalid)
for step in indices[1:]:
self.assertEqual(m[start:stop:step],
s[start:stop:step])
def test_extended_set_del_slice(self):
# Test extended slicing by comparing with list slicing.
s = bytes(reversed(range(256)))
m = mmap.mmap(-1, len(s))
indices = (0, None, 1, 3, 19, 300, -1, -2, -31, -300)
for start in indices:
for stop in indices:
# Skip invalid step 0
for step in indices[1:]:
m[:] = s
self.assertEqual(m[:], s)
L = list(s)
# Make sure we have a slice of exactly the right length,
# but with different data.
data = L[start:stop:step]
data = bytes(reversed(data))
L[start:stop:step] = data
m[start:stop:step] = data
self.assertEquals(m[:], bytes(L))
def test_main():
run_unittest(MmapTests)

View file

@ -77,8 +77,7 @@ def play_sound_file(self, data, rate, ssize, nchannels):
# set parameters based on .au file headers
dsp.setparameters(AFMT_S16_NE, nchannels, rate)
print ("playing test sound file (expected running time: %.2f sec)"
% expected_time)
self.assertEquals("%.2f" % expected_time, "2.93")
t1 = time.time()
dsp.write(data)
dsp.close()
@ -121,7 +120,6 @@ def set_parameters(self, dsp):
"setparameters%r: returned %r" % (config, result))
def set_bad_parameters(self, dsp):
# Now try some configurations that are presumably bogus: eg. 300
# channels currently exceeds even Hollywood's ambitions, and
# negative sampling rate is utter nonsense. setparameters() should
@ -166,7 +164,7 @@ def test_set_parameters(self):
def test_main():
try:
dsp = ossaudiodev.open('w')
except IOError as msg:
except (ossaudiodev.error, IOError) as msg:
if msg.args[0] in (errno.EACCES, errno.ENOENT,
errno.ENODEV, errno.EBUSY):
raise TestSkipped(msg)

View file

@ -155,7 +155,8 @@ def test_4(self):
("t4 sub.py", "raise RuntimeError('Shouldnt load sub.py')"),
("t4 sub", None),
("t4 sub __init__.py", ""),
("t4 sub subsub.py", "raise RuntimeError('Shouldnt load subsub.py')"),
("t4 sub subsub.py",
"raise RuntimeError('Shouldnt load subsub.py')"),
("t4 sub subsub", None),
("t4 sub subsub __init__.py", "spam = 1"),
]
@ -196,7 +197,8 @@ def test_5(self):
def test_6(self):
hier = [
("t6", None),
("t6 __init__.py", "__all__ = ['spam', 'ham', 'eggs']"),
("t6 __init__.py",
"__all__ = ['spam', 'ham', 'eggs']"),
("t6 spam.py", ""),
("t6 ham.py", ""),
("t6 eggs.py", ""),
@ -223,10 +225,11 @@ def test_7(self):
("t7.py", ""),
("t7", None),
("t7 __init__.py", ""),
("t7 sub.py", "raise RuntimeError('Shouldnt load sub.py')"),
("t7 sub.py",
"raise RuntimeError('Shouldnt load sub.py')"),
("t7 sub", None),
("t7 sub __init__.py", ""),
("t7 sub subsub.py",
("t7 sub .py",
"raise RuntimeError('Shouldnt load subsub.py')"),
("t7 sub subsub", None),
("t7 sub subsub __init__.py",

View file

@ -5,7 +5,7 @@
import sys
import tempfile
from test.test_support import verbose, run_unittest, forget
from runpy import _run_module_code, run_module
from runpy import _run_code, _run_module_code, _run_module_as_main, run_module
# Set up the test code and expected results
@ -29,6 +29,16 @@ class RunModuleCodeTest(unittest.TestCase):
"nested = runpy._run_module_code('x=1\\n', mod_name='<run>')\n"
)
def test_run_code(self):
saved_argv0 = sys.argv[0]
d = _run_code(self.test_source, {})
self.failUnless(d["result"] == self.expected_result)
self.failUnless(d["__name__"] is None)
self.failUnless(d["__file__"] is None)
self.failUnless(d["__loader__"] is None)
self.failUnless(d["run_argv0"] is saved_argv0)
self.failUnless("run_name" not in d)
self.failUnless(sys.argv[0] is saved_argv0)
def test_run_module_code(self):
initial = object()
@ -37,44 +47,24 @@ def test_run_module_code(self):
loader = "Now you're just being silly"
d1 = dict(initial=initial)
saved_argv0 = sys.argv[0]
try:
d2 = _run_module_code(self.test_source,
d1,
name,
file,
loader,
alter_sys=True)
self.failUnless("result" not in d1)
self.failUnless(d2["initial"] is initial)
self.assertEqual(d2["result"], self.expected_result)
self.assertEqual(d2["nested"]["x"], 1)
self.assertEqual(d2["nested"]["__name__"], "<run>")
self.failUnless(d2["__name__"] is name)
self.failUnless(d2["__file__"] is file)
self.failUnless(d2["__loader__"] is loader)
self.failUnless(d2["run_argv0"] is file)
self.failUnless(d2["run_name_in_sys_modules"])
self.failUnless(d2["module_in_sys_modules"])
self.failUnless(sys.argv[0] is not saved_argv0)
self.failUnless(name in sys.modules)
finally:
sys.argv[0] = saved_argv0
if name in sys.modules:
del sys.modules[name]
def test_run_module_code_defaults(self):
saved_argv0 = sys.argv[0]
d = _run_module_code(self.test_source)
self.assertEqual(d["result"], self.expected_result)
self.failUnless(d["nested"]["x"] == 1)
self.failUnless(d["nested"]["__name__"] == "<run>")
self.failUnless(d["__name__"] is None)
self.failUnless(d["__file__"] is None)
self.failUnless(d["__loader__"] is None)
self.failUnless(d["run_argv0"] is saved_argv0)
self.failUnless(not d["run_name_in_sys_modules"])
d2 = _run_module_code(self.test_source,
d1,
name,
file,
loader)
self.failUnless("result" not in d1)
self.failUnless(d2["initial"] is initial)
self.assertEqual(d2["result"], self.expected_result)
self.assertEqual(d2["nested"]["x"], 1)
self.failUnless(d2["__name__"] is name)
self.failUnless(d2["run_name_in_sys_modules"])
self.failUnless(d2["module_in_sys_modules"])
self.failUnless(d2["__file__"] is file)
self.failUnless(d2["run_argv0"] is file)
self.failUnless(d2["__loader__"] is loader)
self.failUnless(sys.argv[0] is saved_argv0)
self.failUnless(None not in sys.modules)
self.failUnless(name not in sys.modules)
class RunModuleTest(unittest.TestCase):

View file

@ -1,167 +1,178 @@
# Test the signal module
from test.test_support import verbose, TestSkipped, TestFailed, vereq
import unittest
from test import test_support
import signal
import os, sys, time
if sys.platform[:3] in ('win', 'os2'):
raise TestSkipped, "Can't test signal on %s" % sys.platform
MAX_DURATION = 20 # Entire test should last at most 20 sec.
if verbose:
x = '-x'
else:
x = '+x'
pid = os.getpid()
if verbose:
print("test runner's pid is", pid)
# Shell script that will send us asynchronous signals
script = """
(
set %(x)s
sleep 2
kill -HUP %(pid)d
sleep 2
kill -USR1 %(pid)d
sleep 2
kill -USR2 %(pid)d
) &
""" % vars()
a_called = b_called = False
def handlerA(*args):
global a_called
a_called = True
if verbose:
print("handlerA invoked", args)
class HandlerBCalled(Exception):
pass
def handlerB(*args):
global b_called
b_called = True
if verbose:
print("handlerB invoked", args)
raise HandlerBCalled, args
class InterProcessSignalTests(unittest.TestCase):
MAX_DURATION = 20 # Entire test should last at most 20 sec.
# Set up a child to send signals to us (the parent) after waiting long
# enough to receive the alarm. It seems we miss the alarm for some
# reason. This will hopefully stop the hangs on Tru64/Alpha.
# Alas, it doesn't. Tru64 appears to miss all the signals at times, or
# seemingly random subsets of them, and nothing done in force_test_exit
# so far has actually helped.
def force_test_exit():
# Sigh, both imports seem necessary to avoid errors.
import os
fork_pid = os.fork()
if fork_pid:
# In parent.
return fork_pid
# Set up a child to send signals to us (the parent) after waiting
# long enough to receive the alarm. It seems we miss the alarm
# for some reason. This will hopefully stop the hangs on
# Tru64/Alpha. Alas, it doesn't. Tru64 appears to miss all the
# signals at times, or seemingly random subsets of them, and
# nothing done in force_test_exit so far has actually helped.
def spawn_force_test_exit_process(self, parent_pid):
# Sigh, both imports seem necessary to avoid errors.
import os
fork_pid = os.fork()
if fork_pid:
# In parent.
return fork_pid
# In child.
import os, time
try:
# Wait 5 seconds longer than the expected alarm to give enough
# time for the normal sequence of events to occur. This is
# just a stop-gap to try to prevent the test from hanging.
time.sleep(MAX_DURATION + 5)
print(' child should not have to kill parent', file=sys.__stdout__)
for signame in "SIGHUP", "SIGUSR1", "SIGUSR2", "SIGALRM":
os.kill(pid, getattr(signal, signame))
print(" child sent", signame, "to", pid, file=sys.__stdout__)
time.sleep(1)
finally:
os._exit(0)
# In child.
import os, time
try:
# Wait 5 seconds longer than the expected alarm to give enough
# time for the normal sequence of events to occur. This is
# just a stop-gap to try to prevent the test from hanging.
time.sleep(self.MAX_DURATION + 5)
print(" child should not have to kill parent",
file=sys.__stdout__)
for signame in "SIGHUP", "SIGUSR1", "SIGUSR2", "SIGALRM":
os.kill(parent_pid, getattr(signal, signame))
print(" child sent", signame, "to",
parent_pid, file=sys.__stdout__)
time.sleep(1)
finally:
os._exit(0)
# Install handlers.
hup = signal.signal(signal.SIGHUP, handlerA)
usr1 = signal.signal(signal.SIGUSR1, handlerB)
usr2 = signal.signal(signal.SIGUSR2, signal.SIG_IGN)
alrm = signal.signal(signal.SIGALRM, signal.default_int_handler)
def handlerA(self, *args):
self.a_called = True
if test_support.verbose:
print("handlerA invoked", args)
try:
def handlerB(self, *args):
self.b_called = True
if test_support.verbose:
print("handlerB invoked", args)
raise HandlerBCalled(*args)
signal.alarm(MAX_DURATION)
vereq(signal.getsignal(signal.SIGHUP), handlerA)
vereq(signal.getsignal(signal.SIGUSR1), handlerB)
vereq(signal.getsignal(signal.SIGUSR2), signal.SIG_IGN)
vereq(signal.getsignal(signal.SIGALRM), signal.default_int_handler)
def test_main(self):
self.assertEquals(signal.getsignal(signal.SIGHUP), self.handlerA)
self.assertEquals(signal.getsignal(signal.SIGUSR1), self.handlerB)
self.assertEquals(signal.getsignal(signal.SIGUSR2), signal.SIG_IGN)
self.assertEquals(signal.getsignal(signal.SIGALRM),
signal.default_int_handler)
# Try to ensure this test exits even if there is some problem with alarm.
# Tru64/Alpha often hangs and is ultimately killed by the buildbot.
fork_pid = force_test_exit()
# Launch an external script to send us signals.
# We expect the external script to:
# send HUP, which invokes handlerA to set a_called
# send USR1, which invokes handlerB to set b_called and raise
# HandlerBCalled
# send USR2, which is ignored
#
# Then we expect the alarm to go off, and its handler raises
# KeyboardInterrupt, finally getting us out of the loop.
try:
signal.getsignal(4242)
raise TestFailed('expected ValueError for invalid signal # to '
'getsignal()')
except ValueError:
pass
if test_support.verbose:
verboseflag = '-x'
else:
verboseflag = '+x'
try:
signal.signal(4242, handlerB)
raise TestFailed('expected ValueError for invalid signal # to '
'signal()')
except ValueError:
pass
pid = self.pid
if test_support.verbose:
print("test runner's pid is", pid)
try:
signal.signal(signal.SIGUSR1, None)
raise TestFailed('expected TypeError for non-callable')
except TypeError:
pass
# Shell script that will send us asynchronous signals
script = """
(
set %(verboseflag)s
sleep 2
kill -HUP %(pid)d
sleep 2
kill -USR1 %(pid)d
sleep 2
kill -USR2 %(pid)d
) &
""" % vars()
# Launch an external script to send us signals.
# We expect the external script to:
# send HUP, which invokes handlerA to set a_called
# send USR1, which invokes handlerB to set b_called and raise
# HandlerBCalled
# send USR2, which is ignored
#
# Then we expect the alarm to go off, and its handler raises
# KeyboardInterrupt, finally getting us out of the loop.
os.system(script)
try:
print("starting pause() loop...")
while 1:
try:
if verbose:
print("call pause()...")
signal.pause()
if verbose:
print("pause() returned")
except HandlerBCalled:
if verbose:
print("HandlerBCalled exception caught")
signal.alarm(self.MAX_DURATION)
except KeyboardInterrupt:
if verbose:
print("KeyboardInterrupt (the alarm() went off)")
handler_b_exception_raised = False
if not a_called:
print('HandlerA not called')
os.system(script)
try:
if test_support.verbose:
print("starting pause() loop...")
while 1:
try:
if test_support.verbose:
print("call pause()...")
signal.pause()
if test_support.verbose:
print("pause() returned")
except HandlerBCalled:
handler_b_exception_raised = True
if test_support.verbose:
print("HandlerBCalled exception caught")
if not b_called:
print('HandlerB not called')
except KeyboardInterrupt:
if test_support.verbose:
print("KeyboardInterrupt (the alarm() went off)")
finally:
# Forcibly kill the child we created to ping us if there was a test error.
try:
# Make sure we don't kill ourself if there was a fork error.
if fork_pid > 0:
os.kill(fork_pid, signal.SIGKILL)
except:
# If the child killed us, it has probably exited. Killing a
# non-existent process will raise an error which we don't care about.
pass
self.assert_(self.a_called)
self.assert_(self.b_called)
self.assert_(handler_b_exception_raised)
# Restore handlers.
signal.alarm(0) # cancel alarm in case we died early
signal.signal(signal.SIGHUP, hup)
signal.signal(signal.SIGUSR1, usr1)
signal.signal(signal.SIGUSR2, usr2)
signal.signal(signal.SIGALRM, alrm)
def setUp(self):
# Install handlers.
self.hup = signal.signal(signal.SIGHUP, self.handlerA)
self.usr1 = signal.signal(signal.SIGUSR1, self.handlerB)
self.usr2 = signal.signal(signal.SIGUSR2, signal.SIG_IGN)
self.alrm = signal.signal(signal.SIGALRM,
signal.default_int_handler)
self.a_called = False
self.b_called = False
self.pid = os.getpid()
self.fork_pid = self.spawn_force_test_exit_process(self.pid)
def tearDown(self):
# Forcibly kill the child we created to ping us if there was a
# test error.
try:
# Make sure we don't kill ourself if there was a fork
# error.
if self.fork_pid > 0:
os.kill(self.fork_pid, signal.SIGKILL)
except:
# If the child killed us, it has probably exited. Killing
# a non-existent process will raise an error which we
# don't care about.
pass
# Restore handlers.
signal.alarm(0) # cancel alarm in case we died early
signal.signal(signal.SIGHUP, self.hup)
signal.signal(signal.SIGUSR1, self.usr1)
signal.signal(signal.SIGUSR2, self.usr2)
signal.signal(signal.SIGALRM, self.alrm)
class BasicSignalTests(unittest.TestCase):
def test_out_of_range_signal_number_raises_error(self):
self.assertRaises(ValueError, signal.getsignal, 4242)
def trivial_signal_handler(*args):
pass
self.assertRaises(ValueError, signal.signal, 4242,
trivial_signal_handler)
def test_setting_signal_handler_to_none_raises_error(self):
self.assertRaises(TypeError, signal.signal,
signal.SIGUSR1, None)
def test_main():
if sys.platform[:3] in ('win', 'os2'):
raise test_support.TestSkipped("Can't test signal on %s" % \
sys.platform)
test_support.run_unittest(BasicSignalTests, InterProcessSignalTests)
if __name__ == "__main__":
test_main()

372
Lib/test/test_ssl.py Normal file
View file

@ -0,0 +1,372 @@
# Test the support for SSL and sockets
import sys
import unittest
from test import test_support
import socket
import errno
import threading
import subprocess
import time
import os
import pprint
import urllib
import shutil
import traceback
# Optionally test SSL support, if we have it in the tested platform
skip_expected = False
try:
import ssl
except ImportError:
skip_expected = True
CERTFILE = None
def handle_error(prefix):
exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
sys.stdout.write(prefix + exc_format)
class BasicTests(unittest.TestCase):
def testRudeShutdown(self):
# Some random port to connect to.
PORT = [9934]
listener_ready = threading.Event()
listener_gone = threading.Event()
# `listener` runs in a thread. It opens a socket listening on
# PORT, and sits in an accept() until the main thread connects.
# Then it rudely closes the socket, and sets Event `listener_gone`
# to let the main thread know the socket is gone.
def listener():
s = socket.socket()
PORT[0] = test_support.bind_port(s, '', PORT[0])
s.listen(5)
listener_ready.set()
s.accept()
s = None # reclaim the socket object, which also closes it
listener_gone.set()
def connector():
listener_ready.wait()
s = socket.socket()
s.connect(('localhost', PORT[0]))
listener_gone.wait()
try:
ssl_sock = socket.ssl(s)
except socket.sslerror:
pass
else:
raise test_support.TestFailed(
'connecting to closed SSL socket should have failed')
t = threading.Thread(target=listener)
t.start()
connector()
t.join()
def testSSLconnect(self):
import os
with test_support.transient_internet():
s = ssl.sslsocket(socket.socket(socket.AF_INET),
cert_reqs=ssl.CERT_NONE)
s.connect(("pop.gmail.com", 995))
c = s.getpeercert()
if c:
raise test_support.TestFailed("Peer cert %s shouldn't be here!")
s.close()
# this should fail because we have no verification certs
s = ssl.sslsocket(socket.socket(socket.AF_INET),
cert_reqs=ssl.CERT_REQUIRED)
try:
s.connect(("pop.gmail.com", 995))
except ssl.sslerror:
pass
finally:
s.close()
class ConnectedTests(unittest.TestCase):
def testTLSecho (self):
s1 = socket.socket()
try:
s1.connect(('127.0.0.1', 10024))
except:
handle_error("connection failure:\n")
raise test_support.TestFailed("Can't connect to test server")
else:
try:
c1 = ssl.sslsocket(s1, ssl_version=ssl.PROTOCOL_TLSv1)
except:
handle_error("SSL handshake failure:\n")
raise test_support.TestFailed("Can't SSL-handshake with test server")
else:
if not c1:
raise test_support.TestFailed("Can't SSL-handshake with test server")
indata = "FOO\n"
c1.write(indata)
outdata = c1.read()
if outdata != indata.lower():
raise test_support.TestFailed("bad data <<%s>> received; expected <<%s>>\n" % (data, indata.lower()))
c1.close()
def testReadCert(self):
s2 = socket.socket()
try:
s2.connect(('127.0.0.1', 10024))
except:
handle_error("connection failure:\n")
raise test_support.TestFailed("Can't connect to test server")
else:
try:
c2 = ssl.sslsocket(s2, ssl_version=ssl.PROTOCOL_TLSv1,
cert_reqs=ssl.CERT_REQUIRED, ca_certs=CERTFILE)
except:
handle_error("SSL handshake failure:\n")
raise test_support.TestFailed("Can't SSL-handshake with test server")
else:
if not c2:
raise test_support.TestFailed("Can't SSL-handshake with test server")
cert = c2.getpeercert()
if not cert:
raise test_support.TestFailed("Can't get peer certificate.")
if not cert.has_key('subject'):
raise test_support.TestFailed(
"No subject field in certificate: %s." %
pprint.pformat(cert))
if not (cert['subject'].has_key('organizationName')):
raise test_support.TestFailed(
"No 'organizationName' field in certificate subject: %s." %
pprint.pformat(cert))
if (cert['subject']['organizationName'] !=
"Python Software Foundation"):
raise test_support.TestFailed(
"Invalid 'organizationName' field in certificate subject; "
"should be 'Python Software Foundation'.");
c2.close()
class ThreadedEchoServer(threading.Thread):
class ConnectionHandler(threading.Thread):
def __init__(self, server, connsock):
self.server = server
self.running = False
self.sock = connsock
threading.Thread.__init__(self)
self.setDaemon(True)
def run (self):
self.running = True
try:
sslconn = ssl.sslsocket(self.sock, server_side=True,
certfile=self.server.certificate,
ssl_version=self.server.protocol,
cert_reqs=self.server.certreqs)
except:
# here, we want to stop the server, because this shouldn't
# happen in the context of our test case
handle_error("Test server failure:\n")
self.running = False
# normally, we'd just stop here, but for the test
# harness, we want to stop the server
self.server.stop()
return
while self.running:
try:
msg = sslconn.read()
if not msg:
# eof, so quit this handler
self.running = False
sslconn.close()
elif msg.strip() == 'over':
sslconn.close()
self.server.stop()
self.running = False
else:
if test_support.verbose:
sys.stdout.write("\nserver: %s\n" % msg.strip().lower())
sslconn.write(msg.lower())
except ssl.sslerror:
handle_error("Test server failure:\n")
sslconn.close()
self.running = False
# normally, we'd just stop here, but for the test
# harness, we want to stop the server
self.server.stop()
except:
handle_error('')
def __init__(self, port, certificate, ssl_version=None,
certreqs=None, cacerts=None):
if ssl_version is None:
ssl_version = ssl.PROTOCOL_TLSv1
if certreqs is None:
certreqs = ssl.CERT_NONE
self.certificate = certificate
self.protocol = ssl_version
self.certreqs = certreqs
self.cacerts = cacerts
self.sock = socket.socket()
self.flag = None
if hasattr(socket, 'SO_REUSEADDR'):
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
if hasattr(socket, 'SO_REUSEPORT'):
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
self.sock.bind(('127.0.0.1', port))
self.active = False
threading.Thread.__init__(self)
self.setDaemon(False)
def start (self, flag=None):
self.flag = flag
threading.Thread.start(self)
def run (self):
self.sock.settimeout(0.5)
self.sock.listen(5)
self.active = True
if self.flag:
# signal an event
self.flag.set()
while self.active:
try:
newconn, connaddr = self.sock.accept()
if test_support.verbose:
sys.stdout.write('\nserver: new connection from ' + str(connaddr) + '\n')
handler = self.ConnectionHandler(self, newconn)
handler.start()
except socket.timeout:
pass
except KeyboardInterrupt:
self.stop()
except:
handle_error("Test server failure:\n")
def stop (self):
self.active = False
self.sock.close()
CERTFILE_CONFIG_TEMPLATE = """
# create RSA certs - Server
[ req ]
default_bits = 1024
encrypt_key = yes
distinguished_name = req_dn
x509_extensions = cert_type
[ req_dn ]
countryName = Country Name (2 letter code)
countryName_default = US
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = %(state)s
localityName = Locality Name (eg, city)
localityName_default = %(city)s
0.organizationName = Organization Name (eg, company)
0.organizationName_default = %(organization)s
organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = %(unit)s
0.commonName = Common Name (FQDN of your server)
0.commonName_default = %(common-name)s
# To create a certificate for more than one name uncomment:
# 1.commonName = DNS alias of your server
# 2.commonName = DNS alias of your server
# ...
# See http://home.netscape.com/eng/security/ssl_2.0_certificate.html
# to see how Netscape understands commonName.
[ cert_type ]
nsCertType = server
"""
def create_cert_files(hostname=None):
"""This is the routine that was run to create the certificate
and private key contained in keycert.pem."""
import tempfile, socket, os
d = tempfile.mkdtemp()
# now create a configuration file for the CA signing cert
fqdn = hostname or socket.getfqdn()
crtfile = os.path.join(d, "cert.pem")
conffile = os.path.join(d, "ca.conf")
fp = open(conffile, "w")
fp.write(CERTFILE_CONFIG_TEMPLATE %
{'state': "Delaware",
'city': "Wilmington",
'organization': "Python Software Foundation",
'unit': "SSL",
'common-name': fqdn,
})
fp.close()
error = os.system(
"openssl req -batch -new -x509 -days 2000 -nodes -config %s "
"-keyout \"%s\" -out \"%s\" > /dev/null < /dev/null 2>&1" %
(conffile, crtfile, crtfile))
# now we have a self-signed server cert in crtfile
os.unlink(conffile)
if (os.WEXITSTATUS(error) or
not os.path.exists(crtfile) or os.path.getsize(crtfile) == 0):
if test_support.verbose:
sys.stdout.write("Unable to create certificate for test, "
+ "error status %d\n" % (error >> 8))
crtfile = None
elif test_support.verbose:
sys.stdout.write(open(crtfile, 'r').read() + '\n')
return d, crtfile
def test_main(verbose=False):
if skip_expected:
raise test_support.TestSkipped("socket module has no ssl support")
global CERTFILE
CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
"keycert.pem")
if not CERTFILE:
sys.__stdout__.write("Skipping test_ssl ConnectedTests; "
"couldn't create a certificate.\n")
tests = [BasicTests]
server = None
if CERTFILE and test_support.is_resource_enabled('network'):
server = ThreadedEchoServer(10024, CERTFILE)
flag = threading.Event()
server.start(flag)
# wait for it to start
flag.wait()
tests.append(ConnectedTests)
thread_info = test_support.threading_setup()
try:
test_support.run_unittest(*tests)
finally:
if server is not None and server.active:
server.stop()
# wait for it to stop
server.join()
test_support.threading_cleanup(*thread_info)
if __name__ == "__main__":
test_main()

View file

@ -5,7 +5,7 @@
LONG_MAX, LONG_MIN, ULONG_MAX, \
LLONG_MAX, LLONG_MIN, ULLONG_MAX
import warnings, unittest
import warnings, unittest, sys
from test import test_support
ts=test_structmembersType(1,2,3,4,5,6,7,8,9.99999,10.1010101010)
@ -59,7 +59,7 @@ def test_types(self):
class TestWarnings(unittest.TestCase):
def has_warned(self, w):
self.assert_(w.category is RuntimeWarning)
self.assertEqual(w.category, RuntimeWarning)
def test_byte_max(self):
with test_support.catch_warning() as w:
@ -94,10 +94,13 @@ def test_ushort_max(self):
def test_main(verbose=None):
test_support.run_unittest(
ReadWriteTests,
TestWarnings
)
# Obscure hack so that this test passes after reloads or repeated calls
# to test_main (regrtest -R).
if '__warningregistry__' in globals():
del globals()['__warningregistry__']
if hasattr(sys, '__warningregistry__'):
del sys.__warningregistry__
test_support.run_unittest(__name__)
if __name__ == "__main__":
test_main(verbose=True)

View file

@ -97,6 +97,18 @@ def test_reduce(self):
t = time.gmtime()
x = t.__reduce__()
def test_extended_getslice(self):
# Test extended slicing by comparing with list slicing.
t = time.gmtime()
L = list(t)
indices = (0, None, 1, 3, 19, 300, -1, -2, -31, -300)
for start in indices:
for stop in indices:
# Skip step 0 (invalid)
for step in indices[1:]:
self.assertEqual(list(t[start:stop:step]),
L[start:stop:step])
def test_main():
test_support.run_unittest(StructSeqTest)

View file

@ -362,6 +362,22 @@ def transient_internet():
return contextlib.nested(time_out, socket_peer_reset, ioerror_peer_reset)
@contextlib.contextmanager
def captured_stdout():
"""Run the with statement body using a StringIO object as sys.stdout.
Example use::
with captured_stdout() as s:
print "hello"
assert s.getvalue() == "hello"
"""
import io
orig_stdout = sys.stdout
sys.stdout = io.StringIO()
yield sys.stdout
sys.stdout = orig_stdout
#=======================================================================
# Decorator for running a function in a different locale, correctly resetting
# it afterwards.

View file

@ -140,11 +140,25 @@ def test_fileobj_seek(self):
class MiscReadTest(ReadTest):
def test_no_filename(self):
def test_no_name_argument(self):
fobj = open(self.tarname, "rb")
tar = tarfile.open(fileobj=fobj, mode=self.mode)
self.assertEqual(tar.name, os.path.abspath(fobj.name))
def test_no_name_attribute(self):
data = open(self.tarname, "rb").read()
fobj = io.BytesIO(data)
self.assertRaises(AttributeError, getattr, fobj, "name")
tar = tarfile.open(fileobj=fobj, mode=self.mode)
self.assertEqual(tar.name, None)
def test_empty_name_attribute(self):
data = open(self.tarname, "rb").read()
fobj = io.BytesIO(data)
fobj.name = ""
tar = tarfile.open(fileobj=fobj, mode=self.mode)
self.assertEqual(tar.name, None)
def test_fail_comp(self):
# For Gzip and Bz2 Tests: fail with a ReadError on an uncompressed file.
if self.mode == "r:":

View file

@ -3,6 +3,7 @@
# UserString instances should behave similar to builtin string objects.
import unittest
import string
from test import test_support, string_tests
from UserString import UserString, MutableString
@ -86,6 +87,28 @@ def test_delslice(self):
del s[-1:10]
self.assertEqual(s, "fo")
def test_extended_set_del_slice(self):
indices = (0, None, 1, 3, 19, 100, -1, -2, -31, -100)
orig = string.ascii_letters + string.digits
for start in indices:
for stop in indices:
# Use indices[1:] when MutableString can handle real
# extended slices
for step in (None, 1, -1):
s = self.type2test(orig)
L = list(orig)
# Make sure we have a slice of exactly the right length,
# but with (hopefully) different data.
data = L[start:stop:step]
data.reverse()
L[start:stop:step] = data
s[start:stop:step] = "".join(data)
self.assertEquals(s, "".join(L))
del L[start:stop:step]
del s[start:stop:step]
self.assertEquals(s, "".join(L))
def test_immutable(self):
s = self.type2test("foobar")
s2 = s.immutable()

View file

@ -3,8 +3,9 @@
from _winreg import *
import os, sys
import unittest
from test.test_support import verify
from test import test_support
test_key_name = "SOFTWARE\\Python Registry Test Key - Delete Me"
@ -13,137 +14,152 @@
("String Val", "A string value", REG_SZ),
("StringExpand", "The path is %path%", REG_EXPAND_SZ),
("Multi-string", ["Lots", "of", "string", "values"], REG_MULTI_SZ),
("Raw Data", bytes("binary"+chr(0)+"data"), REG_BINARY),
("Raw Data", b"binary\x00data", REG_BINARY),
("Big String", "x"*(2**14-1), REG_SZ),
("Big Binary", b"x"*(2**14), REG_BINARY),
]
def WriteTestData(root_key):
# Set the default value for this key.
SetValue(root_key, test_key_name, REG_SZ, "Default value")
key = CreateKey(root_key, test_key_name)
# Create a sub-key
sub_key = CreateKey(key, "sub_key")
# Give the sub-key some named values
for value_name, value_data, value_type in test_data:
SetValueEx(sub_key, value_name, 0, value_type, value_data)
# Check we wrote as many items as we thought.
nkeys, nvalues, since_mod = QueryInfoKey(key)
verify(nkeys==1, "Not the correct number of sub keys")
verify(nvalues==1, "Not the correct number of values")
nkeys, nvalues, since_mod = QueryInfoKey(sub_key)
verify(nkeys==0, "Not the correct number of sub keys")
verify(nvalues==len(test_data), "Not the correct number of values")
# Close this key this way...
# (but before we do, copy the key as an integer - this allows
# us to test that the key really gets closed).
int_sub_key = int(sub_key)
CloseKey(sub_key)
try:
QueryInfoKey(int_sub_key)
raise RuntimeError, "It appears the CloseKey() function does not close the actual key!"
except EnvironmentError:
pass
# ... and close that key that way :-)
int_key = int(key)
key.Close()
try:
QueryInfoKey(int_key)
raise RuntimeError, "It appears the key.Close() function does not close the actual key!"
except EnvironmentError:
pass
def ReadTestData(root_key):
# Check we can get default value for this key.
val = QueryValue(root_key, test_key_name)
verify(type(val) is str and val=="Default value", "Registry didn't give back the correct value")
key = OpenKey(root_key, test_key_name)
# Read the sub-keys
sub_key = OpenKey(key, "sub_key")
# Check I can enumerate over the values.
index = 0
while 1:
try:
data = EnumValue(sub_key, index)
except EnvironmentError:
break
verify(data in test_data, "Didn't read back the correct test data")
index = index + 1
verify(index==len(test_data), "Didn't read the correct number of items")
# Check I can directly access each item
for value_name, value_data, value_type in test_data:
read_val, read_typ = QueryValueEx(sub_key, value_name)
verify(read_val==value_data and read_typ == value_type, \
"Could not directly read the value" )
sub_key.Close()
# Enumerate our main key.
read_val = EnumKey(key, 0)
verify(read_val == "sub_key", "Read subkey value wrong")
try:
EnumKey(key, 1)
verify(0, "Was able to get a second key when I only have one!")
except EnvironmentError:
pass
key.Close()
def DeleteTestData(root_key):
key = OpenKey(root_key, test_key_name, 0, KEY_ALL_ACCESS)
sub_key = OpenKey(key, "sub_key", 0, KEY_ALL_ACCESS)
# It is not necessary to delete the values before deleting
# the key (although subkeys must not exist). We delete them
# manually just to prove we can :-)
for value_name, value_data, value_type in test_data:
DeleteValue(sub_key, value_name)
nkeys, nvalues, since_mod = QueryInfoKey(sub_key)
verify(nkeys==0 and nvalues==0, "subkey not empty before delete")
sub_key.Close()
DeleteKey(key, "sub_key")
try:
# Shouldnt be able to delete it twice!
DeleteKey(key, "sub_key")
verify(0, "Deleting the key twice succeeded")
except EnvironmentError:
pass
key.Close()
DeleteKey(root_key, test_key_name)
# Opening should now fail!
try:
key = OpenKey(root_key, test_key_name)
verify(0, "Could open the non-existent key")
except WindowsError: # Use this error name this time
pass
def TestAll(root_key):
WriteTestData(root_key)
ReadTestData(root_key)
DeleteTestData(root_key)
# Test on my local machine.
TestAll(HKEY_CURRENT_USER)
print("Local registry tests worked")
try:
remote_name = sys.argv[sys.argv.index("--remote")+1]
except (IndexError, ValueError):
class WinregTests(unittest.TestCase):
remote_name = None
if remote_name is not None:
def WriteTestData(self, root_key):
# Set the default value for this key.
SetValue(root_key, test_key_name, REG_SZ, "Default value")
key = CreateKey(root_key, test_key_name)
# Create a sub-key
sub_key = CreateKey(key, "sub_key")
# Give the sub-key some named values
for value_name, value_data, value_type in test_data:
SetValueEx(sub_key, value_name, 0, value_type, value_data)
# Check we wrote as many items as we thought.
nkeys, nvalues, since_mod = QueryInfoKey(key)
self.assertEquals(nkeys, 1, "Not the correct number of sub keys")
self.assertEquals(nvalues, 1, "Not the correct number of values")
nkeys, nvalues, since_mod = QueryInfoKey(sub_key)
self.assertEquals(nkeys, 0, "Not the correct number of sub keys")
self.assertEquals(nvalues, len(test_data),
"Not the correct number of values")
# Close this key this way...
# (but before we do, copy the key as an integer - this allows
# us to test that the key really gets closed).
int_sub_key = int(sub_key)
CloseKey(sub_key)
try:
QueryInfoKey(int_sub_key)
self.fail("It appears the CloseKey() function does "
"not close the actual key!")
except EnvironmentError:
pass
# ... and close that key that way :-)
int_key = int(key)
key.Close()
try:
QueryInfoKey(int_key)
self.fail("It appears the key.Close() function "
"does not close the actual key!")
except EnvironmentError:
pass
def ReadTestData(self, root_key):
# Check we can get default value for this key.
val = QueryValue(root_key, test_key_name)
self.assertEquals(val, "Default value",
"Registry didn't give back the correct value")
key = OpenKey(root_key, test_key_name)
# Read the sub-keys
sub_key = OpenKey(key, "sub_key")
# Check I can enumerate over the values.
index = 0
while 1:
try:
data = EnumValue(sub_key, index)
except EnvironmentError:
break
self.assertEquals(data in test_data, True,
"Didn't read back the correct test data")
index = index + 1
self.assertEquals(index, len(test_data),
"Didn't read the correct number of items")
# Check I can directly access each item
for value_name, value_data, value_type in test_data:
read_val, read_typ = QueryValueEx(sub_key, value_name)
self.assertEquals(read_val, value_data,
"Could not directly read the value")
self.assertEquals(read_typ, value_type,
"Could not directly read the value")
sub_key.Close()
# Enumerate our main key.
read_val = EnumKey(key, 0)
self.assertEquals(read_val, "sub_key", "Read subkey value wrong")
try:
EnumKey(key, 1)
self.fail("Was able to get a second key when I only have one!")
except EnvironmentError:
pass
key.Close()
def DeleteTestData(self, root_key):
key = OpenKey(root_key, test_key_name, 0, KEY_ALL_ACCESS)
sub_key = OpenKey(key, "sub_key", 0, KEY_ALL_ACCESS)
# It is not necessary to delete the values before deleting
# the key (although subkeys must not exist). We delete them
# manually just to prove we can :-)
for value_name, value_data, value_type in test_data:
DeleteValue(sub_key, value_name)
nkeys, nvalues, since_mod = QueryInfoKey(sub_key)
self.assertEquals(nkeys, 0, "subkey not empty before delete")
self.assertEquals(nvalues, 0, "subkey not empty before delete")
sub_key.Close()
DeleteKey(key, "sub_key")
try:
# Shouldnt be able to delete it twice!
DeleteKey(key, "sub_key")
self.fail("Deleting the key twice succeeded")
except EnvironmentError:
pass
key.Close()
DeleteKey(root_key, test_key_name)
# Opening should now fail!
try:
key = OpenKey(root_key, test_key_name)
self.fail("Could open the non-existent key")
except WindowsError: # Use this error name this time
pass
def TestAll(self, root_key):
self.WriteTestData(root_key)
self.ReadTestData(root_key)
self.DeleteTestData(root_key)
def testLocalMachineRegistryWorks(self):
self.TestAll(HKEY_CURRENT_USER)
def testConnectRegistryToLocalMachineWorks(self):
# perform minimal ConnectRegistry test which just invokes it
h = ConnectRegistry(None, HKEY_LOCAL_MACHINE)
h.Close()
def testRemoteMachineRegistryWorks(self):
if not self.remote_name:
raise test_support.TestSkipped("Remote machine name "
"not specified.")
remote_key = ConnectRegistry(self.remote_name, HKEY_CURRENT_USER)
self.TestAll(remote_key)
def test_main():
test_support.run_unittest(WinregTests)
if __name__ == "__main__":
try:
remote_key = ConnectRegistry(remote_name, HKEY_CURRENT_USER)
except EnvironmentError as exc:
print("Could not connect to the remote machine -", exc.strerror)
remote_key = None
if remote_key is not None:
TestAll(remote_key)
print("Remote registry tests worked")
else:
print("Remote registry calls can be tested using", end=' ')
print("'test_winreg.py --remote \\\\machine_name'")
# perform minimal ConnectRegistry test which just invokes it
h = ConnectRegistry(None, HKEY_LOCAL_MACHINE)
h.Close()
WinregTests.remote_name = sys.argv[sys.argv.index("--remote")+1]
except (IndexError, ValueError):
print("Remote registry calls can be tested using",
"'test_winreg.py --remote \\\\machine_name'")
WinregTests.remote_name = None
test_main()

View file

@ -284,6 +284,27 @@ def div(self, x, y):
evt.set()
def is_unavailable_exception(e):
'''Returns True if the given ProtocolError is the product of a server-side
exception caused by the 'temporarily unavailable' response sometimes
given by operations on non-blocking sockets.'''
# sometimes we get a -1 error code and/or empty headers
if e.errcode == -1 or e.headers is None:
return True
exc_mess = e.headers.get('X-exception')
if exc_mess and 'temporarily unavailable' in exc_mess.lower():
return True
return False
# NOTE: The tests in SimpleServerTestCase will ignore failures caused by
# "temporarily unavailable" exceptions raised in SimpleXMLRPCServer. This
# condition occurs infrequently on some platforms, frequently on others, and
# is apparently caused by using SimpleXMLRPCServer with a non-blocking socket.
# If the server class is updated at some point in the future to handle this
# situation more gracefully, these tests should be modified appropriately.
class SimpleServerTestCase(unittest.TestCase):
def setUp(self):
# enable traceback reporting
@ -291,7 +312,7 @@ def setUp(self):
self.evt = threading.Event()
# start server thread to handle requests
serv_args = (self.evt, 2)
serv_args = (self.evt, 1)
threading.Thread(target=http_server, args=serv_args).start()
# wait for port to be assigned to server
@ -314,8 +335,10 @@ def test_simple1(self):
p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT)
self.assertEqual(p.pow(6,8), 6**8)
except xmlrpclib.ProtocolError as e:
# protocol error; provide additional information in test output
self.fail("%s\n%s" % (e, e.headers))
# ignore failures due to non-blocking socket 'unavailable' errors
if not is_unavailable_exception(e):
# protocol error; provide additional information in test output
self.fail("%s\n%s" % (e, e.headers))
def test_introspection1(self):
try:
@ -325,8 +348,10 @@ def test_introspection1(self):
'system.methodHelp', 'system.methodSignature', 'system.multicall'])
self.assertEqual(set(meth), expected_methods)
except xmlrpclib.ProtocolError as e:
# protocol error; provide additional information in test output
self.fail("%s\n%s" % (e, e.headers))
# ignore failures due to non-blocking socket 'unavailable' errors
if not is_unavailable_exception(e):
# protocol error; provide additional information in test output
self.fail("%s\n%s" % (e, e.headers))
def test_introspection2(self):
try:
@ -334,19 +359,23 @@ def test_introspection2(self):
divhelp = p.system.methodHelp('div')
self.assertEqual(divhelp, 'This is the div function')
except xmlrpclib.ProtocolError as e:
# protocol error; provide additional information in test output
self.fail("%s\n%s" % (e, e.headers))
# ignore failures due to non-blocking socket 'unavailable' errors
if not is_unavailable_exception(e):
# protocol error; provide additional information in test output
self.fail("%s\n%s" % (e, e.headers))
def test_introspection3(self):
# the SimpleXMLRPCServer doesn't support signatures, but
# at least check that we can try
# at least check that we can try making the call
try:
p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT)
divsig = p.system.methodSignature('div')
self.assertEqual(divsig, 'signatures not supported')
except xmlrpclib.ProtocolError as e:
# protocol error; provide additional information in test output
self.fail("%s\n%s" % (e, e.headers))
# ignore failures due to non-blocking socket 'unavailable' errors
if not is_unavailable_exception(e):
# protocol error; provide additional information in test output
self.fail("%s\n%s" % (e, e.headers))
def test_multicall(self):
try:
@ -360,8 +389,10 @@ def test_multicall(self):
self.assertEqual(pow_result, 6**8)
self.assertEqual(div_result, 127//42)
except xmlrpclib.ProtocolError as e:
# protocol error; provide additional information in test output
self.fail("%s\n%s" % (e, e.headers))
# ignore failures due to non-blocking socket 'unavailable' errors
if not is_unavailable_exception(e):
# protocol error; provide additional information in test output
self.fail("%s\n%s" % (e, e.headers))
# This is a contrived way to make a failure occur on the server side

View file

@ -1,4 +1,4 @@
/* SSL socket module
/* SSL socket module
SSL support based on patches by Brian E Gallew and Laszlo Kovacs.
@ -8,25 +8,44 @@
*/
#include "Python.h"
enum py_ssl_error {
/* these mirror ssl.h */
PY_SSL_ERROR_NONE,
PY_SSL_ERROR_SSL,
PY_SSL_ERROR_WANT_READ,
PY_SSL_ERROR_WANT_WRITE,
PY_SSL_ERROR_WANT_X509_LOOKUP,
PY_SSL_ERROR_NONE,
PY_SSL_ERROR_SSL,
PY_SSL_ERROR_WANT_READ,
PY_SSL_ERROR_WANT_WRITE,
PY_SSL_ERROR_WANT_X509_LOOKUP,
PY_SSL_ERROR_SYSCALL, /* look at error stack/return value/errno */
PY_SSL_ERROR_ZERO_RETURN,
PY_SSL_ERROR_ZERO_RETURN,
PY_SSL_ERROR_WANT_CONNECT,
/* start of non ssl.h errorcodes */
/* start of non ssl.h errorcodes */
PY_SSL_ERROR_EOF, /* special case of SSL_ERROR_SYSCALL */
PY_SSL_ERROR_INVALID_ERROR_CODE
};
enum py_ssl_server_or_client {
PY_SSL_CLIENT,
PY_SSL_SERVER
};
enum py_ssl_cert_requirements {
PY_SSL_CERT_NONE,
PY_SSL_CERT_OPTIONAL,
PY_SSL_CERT_REQUIRED
};
enum py_ssl_version {
PY_SSL_VERSION_SSL2,
PY_SSL_VERSION_SSL3,
PY_SSL_VERSION_SSL23,
PY_SSL_VERSION_TLS1,
};
/* Include symbols from _socket module */
#include "socketmodule.h"
#if defined(HAVE_POLL_H)
#if defined(HAVE_POLL_H)
#include <poll.h>
#elif defined(HAVE_SYS_POLL_H)
#include <sys/poll.h>
@ -58,10 +77,10 @@ static PyObject *PySSLErrorObject;
typedef struct {
PyObject_HEAD
PySocketSockObject *Socket; /* Socket on which we're layered */
SSL_CTX* ctx;
SSL* ssl;
X509* server_cert;
char server[X509_NAME_MAXLEN];
SSL_CTX* ctx;
SSL* ssl;
X509* peer_cert;
char server[X509_NAME_MAXLEN];
char issuer[X509_NAME_MAXLEN];
} PySSLObject;
@ -69,8 +88,10 @@ typedef struct {
static PyTypeObject PySSL_Type;
static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args);
static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args);
static int check_socket_and_wait_for_timeout(PySocketSockObject *s,
static int check_socket_and_wait_for_timeout(PySocketSockObject *s,
int writing);
static PyObject *PySSL_peercert(PySSLObject *self);
#define PySSLObject_Check(v) (Py_Type(v) == &PySSL_Type)
@ -83,141 +104,181 @@ typedef enum {
SOCKET_OPERATION_OK
} timeout_state;
/* Wrap error strings with filename and line # */
#define STRINGIFY1(x) #x
#define STRINGIFY2(x) STRINGIFY1(x)
#define ERRSTR1(x,y,z) (x ":" y ": " z)
#define ERRSTR(x) ERRSTR1("_ssl.c", STRINGIFY2(__LINE__), x)
/* XXX It might be helpful to augment the error message generated
below with the name of the SSL function that generated the error.
I expect it's obvious most of the time.
*/
static PyObject *
PySSL_SetError(PySSLObject *obj, int ret)
PySSL_SetError(PySSLObject *obj, int ret, char *filename, int lineno)
{
PyObject *v, *n, *s;
PyObject *v;
char buf[2048];
char *errstr;
int err;
enum py_ssl_error p;
enum py_ssl_error p = PY_SSL_ERROR_NONE;
assert(ret <= 0);
err = SSL_get_error(obj->ssl, ret);
switch (err) {
case SSL_ERROR_ZERO_RETURN:
errstr = "TLS/SSL connection has been closed";
p = PY_SSL_ERROR_ZERO_RETURN;
break;
case SSL_ERROR_WANT_READ:
errstr = "The operation did not complete (read)";
p = PY_SSL_ERROR_WANT_READ;
break;
case SSL_ERROR_WANT_WRITE:
p = PY_SSL_ERROR_WANT_WRITE;
errstr = "The operation did not complete (write)";
break;
case SSL_ERROR_WANT_X509_LOOKUP:
p = PY_SSL_ERROR_WANT_X509_LOOKUP;
errstr = "The operation did not complete (X509 lookup)";
break;
case SSL_ERROR_WANT_CONNECT:
p = PY_SSL_ERROR_WANT_CONNECT;
errstr = "The operation did not complete (connect)";
break;
case SSL_ERROR_SYSCALL:
{
unsigned long e = ERR_get_error();
if (e == 0) {
if (ret == 0 || !obj->Socket) {
p = PY_SSL_ERROR_EOF;
errstr = "EOF occurred in violation of protocol";
} else if (ret == -1) {
/* the underlying BIO reported an I/O error */
return obj->Socket->errorhandler();
} else { /* possible? */
if ((obj != NULL) && (obj->ssl != NULL)) {
err = SSL_get_error(obj->ssl, ret);
switch (err) {
case SSL_ERROR_ZERO_RETURN:
errstr = "TLS/SSL connection has been closed";
p = PY_SSL_ERROR_ZERO_RETURN;
break;
case SSL_ERROR_WANT_READ:
errstr = "The operation did not complete (read)";
p = PY_SSL_ERROR_WANT_READ;
break;
case SSL_ERROR_WANT_WRITE:
p = PY_SSL_ERROR_WANT_WRITE;
errstr = "The operation did not complete (write)";
break;
case SSL_ERROR_WANT_X509_LOOKUP:
p = PY_SSL_ERROR_WANT_X509_LOOKUP;
errstr =
"The operation did not complete (X509 lookup)";
break;
case SSL_ERROR_WANT_CONNECT:
p = PY_SSL_ERROR_WANT_CONNECT;
errstr = "The operation did not complete (connect)";
break;
case SSL_ERROR_SYSCALL:
{
unsigned long e = ERR_get_error();
if (e == 0) {
if (ret == 0 || !obj->Socket) {
p = PY_SSL_ERROR_EOF;
errstr =
"EOF occurred in violation of protocol";
} else if (ret == -1) {
/* underlying BIO reported an I/O error */
return obj->Socket->errorhandler();
} else { /* possible? */
p = PY_SSL_ERROR_SYSCALL;
errstr = "Some I/O error occurred";
}
} else {
p = PY_SSL_ERROR_SYSCALL;
errstr = "Some I/O error occurred";
/* XXX Protected by global interpreter lock */
errstr = ERR_error_string(e, NULL);
}
} else {
p = PY_SSL_ERROR_SYSCALL;
/* XXX Protected by global interpreter lock */
errstr = ERR_error_string(e, NULL);
break;
}
break;
}
case SSL_ERROR_SSL:
{
unsigned long e = ERR_get_error();
p = PY_SSL_ERROR_SSL;
if (e != 0)
/* XXX Protected by global interpreter lock */
errstr = ERR_error_string(e, NULL);
else { /* possible? */
errstr = "A failure in the SSL library occurred";
case SSL_ERROR_SSL:
{
unsigned long e = ERR_get_error();
p = PY_SSL_ERROR_SSL;
if (e != 0)
/* XXX Protected by global interpreter lock */
errstr = ERR_error_string(e, NULL);
else { /* possible? */
errstr =
"A failure in the SSL library occurred";
}
break;
}
break;
default:
p = PY_SSL_ERROR_INVALID_ERROR_CODE;
errstr = "Invalid error code";
}
} else {
errstr = ERR_error_string(ERR_peek_last_error(), NULL);
}
default:
p = PY_SSL_ERROR_INVALID_ERROR_CODE;
errstr = "Invalid error code";
}
n = PyInt_FromLong((long) p);
if (n == NULL)
return NULL;
v = PyTuple_New(2);
if (v == NULL) {
Py_DECREF(n);
return NULL;
}
s = PyUnicode_FromString(errstr);
if (s == NULL) {
PyOS_snprintf(buf, sizeof(buf), "_ssl.c:%d: %s", lineno, errstr);
v = Py_BuildValue("(is)", p, buf);
if (v != NULL) {
PyErr_SetObject(PySSLErrorObject, v);
Py_DECREF(v);
Py_DECREF(n);
}
PyTuple_SET_ITEM(v, 0, n);
PyTuple_SET_ITEM(v, 1, s);
PyErr_SetObject(PySSLErrorObject, v);
Py_DECREF(v);
return NULL;
}
static PySSLObject *
newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file)
newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file,
enum py_ssl_server_or_client socket_type,
enum py_ssl_cert_requirements certreq,
enum py_ssl_version proto_version,
char *cacerts_file)
{
PySSLObject *self;
char *errstr = NULL;
int ret;
int err;
int sockstate;
int verification_mode;
self = PyObject_New(PySSLObject, &PySSL_Type); /* Create new object */
if (self == NULL)
return NULL;
memset(self->server, '\0', sizeof(char) * X509_NAME_MAXLEN);
memset(self->issuer, '\0', sizeof(char) * X509_NAME_MAXLEN);
self->server_cert = NULL;
self->peer_cert = NULL;
self->ssl = NULL;
self->ctx = NULL;
self->Socket = NULL;
if ((key_file && !cert_file) || (!key_file && cert_file)) {
errstr = "Both the key & certificate files must be specified";
errstr = ERRSTR("Both the key & certificate files "
"must be specified");
goto fail;
}
if ((socket_type == PY_SSL_SERVER) &&
((key_file == NULL) || (cert_file == NULL))) {
errstr = ERRSTR("Both the key & certificate files "
"must be specified for server-side operation");
goto fail;
}
Py_BEGIN_ALLOW_THREADS
self->ctx = SSL_CTX_new(SSLv23_method()); /* Set up context */
if (proto_version == PY_SSL_VERSION_TLS1)
self->ctx = SSL_CTX_new(TLSv1_method()); /* Set up context */
else if (proto_version == PY_SSL_VERSION_SSL3)
self->ctx = SSL_CTX_new(SSLv3_method()); /* Set up context */
else if (proto_version == PY_SSL_VERSION_SSL2)
self->ctx = SSL_CTX_new(SSLv2_method()); /* Set up context */
else
self->ctx = SSL_CTX_new(SSLv23_method()); /* Set up context */
Py_END_ALLOW_THREADS
if (self->ctx == NULL) {
errstr = "SSL_CTX_new error";
errstr = ERRSTR("Invalid SSL protocol variant specified.");
goto fail;
}
if (certreq != PY_SSL_CERT_NONE) {
if (cacerts_file == NULL) {
errstr = ERRSTR("No root certificates specified for "
"verification of other-side certificates.");
goto fail;
} else {
Py_BEGIN_ALLOW_THREADS
ret = SSL_CTX_load_verify_locations(self->ctx,
cacerts_file,
NULL);
Py_END_ALLOW_THREADS
if (ret != 1) {
PySSL_SetError(NULL, 0, __FILE__, __LINE__);
goto fail;
}
}
}
if (key_file) {
Py_BEGIN_ALLOW_THREADS
ret = SSL_CTX_use_PrivateKey_file(self->ctx, key_file,
SSL_FILETYPE_PEM);
SSL_FILETYPE_PEM);
Py_END_ALLOW_THREADS
if (ret < 1) {
errstr = "SSL_CTX_use_PrivateKey_file error";
if (ret != 1) {
PySSL_SetError(NULL, 0, __FILE__, __LINE__);
goto fail;
}
@ -225,16 +286,24 @@ newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file)
ret = SSL_CTX_use_certificate_chain_file(self->ctx,
cert_file);
Py_END_ALLOW_THREADS
SSL_CTX_set_options(self->ctx, SSL_OP_ALL); /* ssl compatibility */
if (ret < 1) {
errstr = "SSL_CTX_use_certificate_chain_file error";
if (ret != 1) {
PySSL_SetError(NULL, 0, __FILE__, __LINE__);
goto fail;
}
/* ssl compatibility */
SSL_CTX_set_options(self->ctx, SSL_OP_ALL);
}
verification_mode = SSL_VERIFY_NONE;
if (certreq == PY_SSL_CERT_OPTIONAL)
verification_mode = SSL_VERIFY_PEER;
else if (certreq == PY_SSL_CERT_REQUIRED)
verification_mode = (SSL_VERIFY_PEER |
SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
SSL_CTX_set_verify(self->ctx, verification_mode,
NULL); /* set verify lvl */
Py_BEGIN_ALLOW_THREADS
SSL_CTX_set_verify(self->ctx,
SSL_VERIFY_NONE, NULL); /* set verify lvl */
self->ssl = SSL_new(self->ctx); /* New ssl struct */
Py_END_ALLOW_THREADS
SSL_set_fd(self->ssl, Sock->sock_fd); /* Set the socket for SSL */
@ -249,7 +318,10 @@ newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file)
}
Py_BEGIN_ALLOW_THREADS
SSL_set_connect_state(self->ssl);
if (socket_type == PY_SSL_CLIENT)
SSL_set_connect_state(self->ssl);
else
SSL_set_accept_state(self->ssl);
Py_END_ALLOW_THREADS
/* Actually negotiate SSL connection */
@ -257,11 +329,14 @@ newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file)
sockstate = 0;
do {
Py_BEGIN_ALLOW_THREADS
ret = SSL_connect(self->ssl);
if (socket_type == PY_SSL_CLIENT)
ret = SSL_connect(self->ssl);
else
ret = SSL_accept(self->ssl);
err = SSL_get_error(self->ssl, ret);
Py_END_ALLOW_THREADS
if(PyErr_CheckSignals()) {
goto fail;
goto fail;
}
if (err == SSL_ERROR_WANT_READ) {
sockstate = check_socket_and_wait_for_timeout(Sock, 0);
@ -270,30 +345,33 @@ newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file)
} else {
sockstate = SOCKET_OPERATION_OK;
}
if (sockstate == SOCKET_HAS_TIMED_OUT) {
PyErr_SetString(PySSLErrorObject, "The connect operation timed out");
if (sockstate == SOCKET_HAS_TIMED_OUT) {
PyErr_SetString(PySSLErrorObject,
ERRSTR("The connect operation timed out"));
goto fail;
} else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
PyErr_SetString(PySSLErrorObject, "Underlying socket has been closed.");
PyErr_SetString(PySSLErrorObject,
ERRSTR("Underlying socket has been closed."));
goto fail;
} else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
PyErr_SetString(PySSLErrorObject, "Underlying socket too large for select().");
PyErr_SetString(PySSLErrorObject,
ERRSTR("Underlying socket too large for select()."));
goto fail;
} else if (sockstate == SOCKET_IS_NONBLOCKING) {
break;
}
} while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE);
if (ret <= 0) {
PySSL_SetError(self, ret);
if (ret < 1) {
PySSL_SetError(self, ret, __FILE__, __LINE__);
goto fail;
}
self->ssl->debug = 1;
Py_BEGIN_ALLOW_THREADS
if ((self->server_cert = SSL_get_peer_certificate(self->ssl))) {
X509_NAME_oneline(X509_get_subject_name(self->server_cert),
if ((self->peer_cert = SSL_get_peer_certificate(self->ssl))) {
X509_NAME_oneline(X509_get_subject_name(self->peer_cert),
self->server, X509_NAME_MAXLEN);
X509_NAME_oneline(X509_get_issuer_name(self->server_cert),
X509_NAME_oneline(X509_get_issuer_name(self->peer_cert),
self->issuer, X509_NAME_MAXLEN);
}
Py_END_ALLOW_THREADS
@ -308,27 +386,41 @@ newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file)
}
static PyObject *
PySocket_ssl(PyObject *self, PyObject *args)
PySSL_sslwrap(PyObject *self, PyObject *args)
{
PySSLObject *rv;
PySocketSockObject *Sock;
int server_side = 0;
int verification_mode = PY_SSL_CERT_NONE;
int protocol = PY_SSL_VERSION_SSL23;
char *key_file = NULL;
char *cert_file = NULL;
char *cacerts_file = NULL;
if (!PyArg_ParseTuple(args, "O!|zz:ssl",
if (!PyArg_ParseTuple(args, "O!i|zziiz:sslwrap",
PySocketModule.Sock_Type,
&Sock,
&key_file, &cert_file))
&server_side,
&key_file, &cert_file,
&verification_mode, &protocol,
&cacerts_file))
return NULL;
rv = newPySSLObject(Sock, key_file, cert_file);
if (rv == NULL)
return NULL;
return (PyObject *)rv;
/*
fprintf(stderr,
"server_side is %d, keyfile %p, certfile %p, verify_mode %d, "
"protocol %d, certs %p\n",
server_side, key_file, cert_file, verification_mode,
protocol, cacerts_file);
*/
return (PyObject *) newPySSLObject(Sock, key_file, cert_file,
server_side, verification_mode,
protocol, cacerts_file);
}
PyDoc_STRVAR(ssl_doc,
"ssl(socket, [keyfile, certfile]) -> sslobject");
"sslwrap(socket, server_side, [keyfile, certfile, certs_mode, protocol,\n"
" cacertsfile]) -> sslobject");
/* SSL object methods */
@ -344,15 +436,163 @@ PySSL_issuer(PySSLObject *self)
return PyUnicode_FromString(self->issuer);
}
static PyObject *
_create_dict_for_X509_NAME (X509_NAME *xname)
{
PyObject *pd = PyDict_New();
int index_counter;
if (pd == NULL)
return NULL;
for (index_counter = 0;
index_counter < X509_NAME_entry_count(xname);
index_counter++)
{
char namebuf[X509_NAME_MAXLEN];
int buflen;
PyObject *name_obj;
ASN1_STRING *value;
PyObject *value_obj;
unsigned char *valuebuf = NULL;
X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname,
index_counter);
ASN1_OBJECT *name = X509_NAME_ENTRY_get_object(entry);
buflen = OBJ_obj2txt(namebuf, sizeof(namebuf), name, 0);
if (buflen < 0)
goto fail0;
name_obj = PyString_FromStringAndSize(namebuf, buflen);
if (name_obj == NULL)
goto fail0;
value = X509_NAME_ENTRY_get_data(entry);
buflen = ASN1_STRING_to_UTF8(&valuebuf, value);
if (buflen < 0) {
Py_DECREF(name_obj);
goto fail0;
}
value_obj = PyUnicode_DecodeUTF8((char *) valuebuf,
buflen, "strict");
OPENSSL_free(valuebuf);
if (value_obj == NULL) {
Py_DECREF(name_obj);
goto fail0;
}
if (PyDict_SetItem(pd, name_obj, value_obj) < 0) {
Py_DECREF(name_obj);
Py_DECREF(value_obj);
goto fail0;
}
Py_DECREF(name_obj);
Py_DECREF(value_obj);
}
return pd;
fail0:
Py_XDECREF(pd);
return NULL;
}
static PyObject *
PySSL_peercert(PySSLObject *self)
{
PyObject *retval = NULL;
BIO *biobuf = NULL;
PyObject *peer;
PyObject *issuer;
PyObject *version;
char buf[2048];
int len;
ASN1_TIME *notBefore, *notAfter;
PyObject *pnotBefore, *pnotAfter;
int verification;
if (!self->peer_cert)
Py_RETURN_NONE;
retval = PyDict_New();
if (retval == NULL)
return NULL;
verification = SSL_CTX_get_verify_mode(self->ctx);
if ((verification & SSL_VERIFY_PEER) == 0)
return retval;
peer = _create_dict_for_X509_NAME(
X509_get_subject_name(self->peer_cert));
if (peer == NULL)
goto fail0;
if (PyDict_SetItemString(retval, (const char *) "subject", peer) < 0) {
Py_DECREF(peer);
goto fail0;
}
Py_DECREF(peer);
issuer = _create_dict_for_X509_NAME(
X509_get_issuer_name(self->peer_cert));
if (issuer == NULL)
goto fail0;
if (PyDict_SetItemString(retval, (const char *)"issuer", issuer) < 0) {
Py_DECREF(issuer);
goto fail0;
}
Py_DECREF(issuer);
version = PyInt_FromLong(X509_get_version(self->peer_cert));
if (PyDict_SetItemString(retval, "version", version) < 0) {
Py_DECREF(version);
goto fail0;
}
Py_DECREF(version);
/* get a memory buffer */
biobuf = BIO_new(BIO_s_mem());
notBefore = X509_get_notBefore(self->peer_cert);
ASN1_TIME_print(biobuf, notBefore);
len = BIO_gets(biobuf, buf, sizeof(buf)-1);
pnotBefore = PyString_FromStringAndSize(buf, len);
if (pnotBefore == NULL)
goto fail1;
if (PyDict_SetItemString(retval, "notBefore", pnotBefore) < 0) {
Py_DECREF(pnotBefore);
goto fail1;
}
Py_DECREF(pnotBefore);
(void) BIO_reset(biobuf);
notAfter = X509_get_notAfter(self->peer_cert);
ASN1_TIME_print(biobuf, notAfter);
len = BIO_gets(biobuf, buf, sizeof(buf)-1);
BIO_free(biobuf);
pnotAfter = PyString_FromStringAndSize(buf, len);
if (pnotAfter == NULL)
goto fail0;
if (PyDict_SetItemString(retval, "notAfter", pnotAfter) < 0) {
Py_DECREF(pnotAfter);
goto fail0;
}
Py_DECREF(pnotAfter);
return retval;
fail1:
if (biobuf != NULL)
BIO_free(biobuf);
fail0:
Py_XDECREF(retval);
return NULL;
}
static void PySSL_dealloc(PySSLObject *self)
{
if (self->server_cert) /* Possible not to have one? */
X509_free (self->server_cert);
if (self->peer_cert) /* Possible not to have one? */
X509_free (self->peer_cert);
if (self->ssl)
SSL_free(self->ssl);
SSL_free(self->ssl);
if (self->ctx)
SSL_CTX_free(self->ctx);
SSL_CTX_free(self->ctx);
Py_XDECREF(self->Socket);
PyObject_Del(self);
}
@ -438,13 +678,16 @@ static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args)
sockstate = check_socket_and_wait_for_timeout(self->Socket, 1);
if (sockstate == SOCKET_HAS_TIMED_OUT) {
PyErr_SetString(PySSLErrorObject, "The write operation timed out");
PyErr_SetString(PySSLErrorObject,
"The write operation timed out");
return NULL;
} else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
PyErr_SetString(PySSLErrorObject, "Underlying socket has been closed.");
PyErr_SetString(PySSLErrorObject,
"Underlying socket has been closed.");
return NULL;
} else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
PyErr_SetString(PySSLErrorObject, "Underlying socket too large for select().");
PyErr_SetString(PySSLErrorObject,
"Underlying socket too large for select().");
return NULL;
}
do {
@ -457,17 +700,21 @@ static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args)
return NULL;
}
if (err == SSL_ERROR_WANT_READ) {
sockstate = check_socket_and_wait_for_timeout(self->Socket, 0);
sockstate =
check_socket_and_wait_for_timeout(self->Socket, 0);
} else if (err == SSL_ERROR_WANT_WRITE) {
sockstate = check_socket_and_wait_for_timeout(self->Socket, 1);
sockstate =
check_socket_and_wait_for_timeout(self->Socket, 1);
} else {
sockstate = SOCKET_OPERATION_OK;
}
if (sockstate == SOCKET_HAS_TIMED_OUT) {
PyErr_SetString(PySSLErrorObject, "The write operation timed out");
if (sockstate == SOCKET_HAS_TIMED_OUT) {
PyErr_SetString(PySSLErrorObject,
"The write operation timed out");
return NULL;
} else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
PyErr_SetString(PySSLErrorObject, "Underlying socket has been closed.");
PyErr_SetString(PySSLErrorObject,
"Underlying socket has been closed.");
return NULL;
} else if (sockstate == SOCKET_IS_NONBLOCKING) {
break;
@ -476,7 +723,7 @@ static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args)
if (len > 0)
return PyInt_FromLong(len);
else
return PySSL_SetError(self, len);
return PySSL_SetError(self, len, __FILE__, __LINE__);
}
PyDoc_STRVAR(PySSL_SSLwrite_doc,
@ -498,7 +745,7 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
if (!(buf = PyBytes_FromStringAndSize((char *) 0, len)))
return NULL;
/* first check if there are bytes ready to be read */
Py_BEGIN_ALLOW_THREADS
count = SSL_pending(self->ssl);
@ -507,12 +754,28 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
if (!count) {
sockstate = check_socket_and_wait_for_timeout(self->Socket, 0);
if (sockstate == SOCKET_HAS_TIMED_OUT) {
PyErr_SetString(PySSLErrorObject, "The read operation timed out");
PyErr_SetString(PySSLErrorObject,
"The read operation timed out");
Py_DECREF(buf);
return NULL;
} else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
PyErr_SetString(PySSLErrorObject, "Underlying socket too large for select().");
PyErr_SetString(PySSLErrorObject,
"Underlying socket too large for select().");
Py_DECREF(buf);
return NULL;
} else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
if (SSL_get_shutdown(self->ssl) !=
SSL_RECEIVED_SHUTDOWN)
{
Py_DECREF(buf);
PyErr_SetString(PySSLErrorObject,
"Socket closed without SSL shutdown handshake");
return NULL;
} else {
/* should contain a zero-length string */
_PyString_Resize(&buf, 0);
return buf;
}
}
}
do {
@ -526,23 +789,32 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
return NULL;
}
if (err == SSL_ERROR_WANT_READ) {
sockstate = check_socket_and_wait_for_timeout(self->Socket, 0);
sockstate =
check_socket_and_wait_for_timeout(self->Socket, 0);
} else if (err == SSL_ERROR_WANT_WRITE) {
sockstate = check_socket_and_wait_for_timeout(self->Socket, 1);
sockstate =
check_socket_and_wait_for_timeout(self->Socket, 1);
} else if ((err == SSL_ERROR_ZERO_RETURN) &&
(SSL_get_shutdown(self->ssl) ==
SSL_RECEIVED_SHUTDOWN))
{
_PyString_Resize(&buf, 0);
return buf;
} else {
sockstate = SOCKET_OPERATION_OK;
}
if (sockstate == SOCKET_HAS_TIMED_OUT) {
PyErr_SetString(PySSLErrorObject, "The read operation timed out");
if (sockstate == SOCKET_HAS_TIMED_OUT) {
PyErr_SetString(PySSLErrorObject,
"The read operation timed out");
Py_DECREF(buf);
return NULL;
} else if (sockstate == SOCKET_IS_NONBLOCKING) {
break;
}
} while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE);
if (count <= 0) {
if (count <= 0) {
Py_DECREF(buf);
return PySSL_SetError(self, count);
return PySSL_SetError(self, count, __FILE__, __LINE__);
}
if (count != len)
if (PyBytes_Resize(buf, count) < 0) {
@ -557,13 +829,49 @@ PyDoc_STRVAR(PySSL_SSLread_doc,
\n\
Read up to len bytes from the SSL socket.");
static PyObject *PySSL_SSLshutdown(PySSLObject *self, PyObject *args)
{
int err;
/* Guard against closed socket */
if (self->Socket->sock_fd < 0) {
PyErr_SetString(PySSLErrorObject,
"Underlying socket has been closed.");
return NULL;
}
Py_BEGIN_ALLOW_THREADS
err = SSL_shutdown(self->ssl);
if (err == 0) {
/* we need to call it again to finish the shutdown */
err = SSL_shutdown(self->ssl);
}
Py_END_ALLOW_THREADS
if (err < 0)
return PySSL_SetError(self, err, __FILE__, __LINE__);
else {
Py_INCREF(self->Socket);
return (PyObject *) (self->Socket);
}
}
PyDoc_STRVAR(PySSL_SSLshutdown_doc,
"shutdown(s) -> socket\n\
\n\
Does the SSL shutdown handshake with the remote end, and returns\n\
the underlying socket object.");
static PyMethodDef PySSLMethods[] = {
{"write", (PyCFunction)PySSL_SSLwrite, METH_VARARGS,
PySSL_SSLwrite_doc},
PySSL_SSLwrite_doc},
{"read", (PyCFunction)PySSL_SSLread, METH_VARARGS,
PySSL_SSLread_doc},
PySSL_SSLread_doc},
{"server", (PyCFunction)PySSL_server, METH_NOARGS},
{"issuer", (PyCFunction)PySSL_issuer, METH_NOARGS},
{"peer_certificate", (PyCFunction)PySSL_peercert, METH_NOARGS},
{"shutdown", (PyCFunction)PySSL_SSLshutdown, METH_NOARGS,
PySSL_SSLshutdown_doc},
{NULL, NULL}
};
@ -574,7 +882,7 @@ static PyObject *PySSL_getattr(PySSLObject *self, char *name)
static PyTypeObject PySSL_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"socket.SSL", /*tp_name*/
"ssl.SSLContext", /*tp_name*/
sizeof(PySSLObject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
@ -649,7 +957,7 @@ PyDoc_STRVAR(PySSL_RAND_egd_doc,
"RAND_egd(path) -> bytes\n\
\n\
Queries the entropy gather daemon (EGD) on socket path. Returns number\n\
of bytes read. Raises socket.sslerror if connection to EGD fails or\n\
of bytes read. Raises ssl.sslerror if connection to EGD fails or\n\
if it does provide enough data to seed PRNG.");
#endif
@ -657,17 +965,17 @@ if it does provide enough data to seed PRNG.");
/* List of functions exported by this module. */
static PyMethodDef PySSL_methods[] = {
{"ssl", PySocket_ssl,
METH_VARARGS, ssl_doc},
{"sslwrap", PySSL_sslwrap,
METH_VARARGS, ssl_doc},
#ifdef HAVE_OPENSSL_RAND
{"RAND_add", PySSL_RAND_add, METH_VARARGS,
{"RAND_add", PySSL_RAND_add, METH_VARARGS,
PySSL_RAND_add_doc},
{"RAND_egd", PySSL_RAND_egd, METH_O,
PySSL_RAND_egd_doc},
{"RAND_status", (PyCFunction)PySSL_RAND_status, METH_NOARGS,
PySSL_RAND_status_doc},
#endif
{NULL, NULL} /* Sentinel */
{NULL, NULL} /* Sentinel */
};
@ -689,19 +997,20 @@ init_ssl(void)
/* Load _socket module and its C API */
if (PySocketModule_ImportModuleAndAPI())
return;
return;
/* Init OpenSSL */
SSL_load_error_strings();
SSLeay_add_ssl_algorithms();
/* Add symbols to module dict */
PySSLErrorObject = PyErr_NewException("socket.sslerror",
PySocketModule.error,
NULL);
PySSLErrorObject = PyErr_NewException("ssl.sslerror",
PySocketModule.error,
NULL);
if (PySSLErrorObject == NULL)
return;
PyDict_SetItemString(d, "sslerror", PySSLErrorObject);
if (PyDict_SetItemString(d, "sslerror", PySSLErrorObject) != 0)
return;
if (PyDict_SetItemString(d, "SSLType",
(PyObject *)&PySSL_Type) != 0)
return;
@ -724,5 +1033,21 @@ init_ssl(void)
PY_SSL_ERROR_EOF);
PyModule_AddIntConstant(m, "SSL_ERROR_INVALID_ERROR_CODE",
PY_SSL_ERROR_INVALID_ERROR_CODE);
/* cert requirements */
PyModule_AddIntConstant(m, "CERT_NONE",
PY_SSL_CERT_NONE);
PyModule_AddIntConstant(m, "CERT_OPTIONAL",
PY_SSL_CERT_OPTIONAL);
PyModule_AddIntConstant(m, "CERT_REQUIRED",
PY_SSL_CERT_REQUIRED);
/* protocol versions */
PyModule_AddIntConstant(m, "PROTOCOL_SSLv2",
PY_SSL_VERSION_SSL2);
PyModule_AddIntConstant(m, "PROTOCOL_SSLv3",
PY_SSL_VERSION_SSL3);
PyModule_AddIntConstant(m, "PROTOCOL_SSLv23",
PY_SSL_VERSION_SSL23);
PyModule_AddIntConstant(m, "PROTOCOL_TLSv1",
PY_SSL_VERSION_TLS1);
}

View file

@ -1596,6 +1596,16 @@ array_subscr(arrayobject* self, PyObject* item)
if (slicelength <= 0) {
return newarrayobject(&Arraytype, 0, self->ob_descr);
}
else if (step == 1) {
PyObject *result = newarrayobject(&Arraytype,
slicelength, self->ob_descr);
if (result == NULL)
return NULL;
memcpy(((arrayobject *)result)->ob_item,
self->ob_item + start * itemsize,
slicelength * itemsize);
return result;
}
else {
result = newarrayobject(&Arraytype, slicelength, self->ob_descr);
if (!result) return NULL;
@ -1614,7 +1624,7 @@ array_subscr(arrayobject* self, PyObject* item)
}
else {
PyErr_SetString(PyExc_TypeError,
"list indices must be integers");
"array indices must be integers");
return NULL;
}
}
@ -1622,112 +1632,146 @@ array_subscr(arrayobject* self, PyObject* item)
static int
array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value)
{
Py_ssize_t start, stop, step, slicelength, needed;
arrayobject* other;
int itemsize;
if (PyIndex_Check(item)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i==-1 && PyErr_Occurred())
if (i == -1 && PyErr_Occurred())
return -1;
if (i < 0)
i += Py_Size(self);
return array_ass_item(self, i, value);
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength;
int itemsize = self->ob_descr->itemsize;
if (PySlice_GetIndicesEx((PySliceObject*)item, Py_Size(self),
&start, &stop, &step, &slicelength) < 0) {
if (i < 0 || i >= Py_Size(self)) {
PyErr_SetString(PyExc_IndexError,
"array assignment index out of range");
return -1;
}
/* treat A[slice(a,b)] = v _exactly_ like A[a:b] = v */
if (step == 1 && ((PySliceObject*)item)->step == Py_None)
return array_ass_slice(self, start, stop, value);
if (value == NULL) {
/* delete slice */
Py_ssize_t cur, i, extra;
if (slicelength <= 0)
return 0;
if (step < 0) {
stop = start + 1;
start = stop + step*(slicelength - 1) - 1;
step = -step;
}
for (cur = start, i = 0; i < slicelength - 1;
cur += step, i++) {
memmove(self->ob_item + (cur - i)*itemsize,
self->ob_item + (cur + 1)*itemsize,
(step - 1) * itemsize);
}
extra = Py_Size(self) - (cur + 1);
if (extra > 0) {
memmove(self->ob_item + (cur - i)*itemsize,
self->ob_item + (cur + 1)*itemsize,
extra*itemsize);
}
Py_Size(self) -= slicelength;
self->ob_item = (char *)PyMem_REALLOC(self->ob_item,
itemsize*Py_Size(self));
self->allocated = Py_Size(self);
return 0;
/* Fall through to slice assignment */
start = i;
stop = i + 1;
step = 1;
slicelength = 1;
}
else {
/* assign slice */
Py_ssize_t cur, i;
arrayobject* av;
if (!array_Check(value)) {
PyErr_Format(PyExc_TypeError,
"must assign array (not \"%.200s\") to slice",
Py_Type(value)->tp_name);
return -1;
}
av = (arrayobject*)value;
if (Py_Size(av) != slicelength) {
PyErr_Format(PyExc_ValueError,
"attempt to assign array of size %ld to extended slice of size %ld",
/*XXX*/(long)Py_Size(av), /*XXX*/(long)slicelength);
return -1;
}
if (!slicelength)
return 0;
/* protect against a[::-1] = a */
if (self == av) {
value = array_slice(av, 0, Py_Size(av));
av = (arrayobject*)value;
if (!av)
return -1;
}
else {
Py_INCREF(value);
}
for (cur = start, i = 0; i < slicelength;
cur += step, i++) {
memcpy(self->ob_item + cur*itemsize,
av->ob_item + i*itemsize,
itemsize);
}
Py_DECREF(value);
return 0;
else
return (*self->ob_descr->setitem)(self, i, value);
}
else if (PySlice_Check(item)) {
if (PySlice_GetIndicesEx((PySliceObject *)item,
Py_Size(self), &start, &stop,
&step, &slicelength) < 0) {
return -1;
}
}
}
else {
PyErr_SetString(PyExc_TypeError,
"list indices must be integers");
PyErr_SetString(PyExc_TypeError,
"array indices must be integer");
return -1;
}
if (value == NULL) {
other = NULL;
needed = 0;
}
else if (array_Check(value)) {
other = (arrayobject *)value;
needed = Py_Size(other);
if (self == other) {
/* Special case "self[i:j] = self" -- copy self first */
int ret;
value = array_slice(other, 0, needed);
if (value == NULL)
return -1;
ret = array_ass_subscr(self, item, value);
Py_DECREF(value);
return ret;
}
if (other->ob_descr != self->ob_descr) {
PyErr_BadArgument();
return -1;
}
}
else {
PyErr_Format(PyExc_TypeError,
"can only assign array (not \"%.200s\") to array slice",
Py_Type(value)->tp_name);
return -1;
}
itemsize = self->ob_descr->itemsize;
/* for 'a[2:1] = ...', the insertion point is 'start', not 'stop' */
if ((step > 0 && stop < start) ||
(step < 0 && stop > start))
stop = start;
if (step == 1) {
if (slicelength > needed) {
memmove(self->ob_item + (start + needed) * itemsize,
self->ob_item + stop * itemsize,
(Py_Size(self) - stop) * itemsize);
if (array_resize(self, Py_Size(self) +
needed - slicelength) < 0)
return -1;
}
else if (slicelength < needed) {
if (array_resize(self, Py_Size(self) +
needed - slicelength) < 0)
return -1;
memmove(self->ob_item + (start + needed) * itemsize,
self->ob_item + stop * itemsize,
(Py_Size(self) - start - needed) * itemsize);
}
if (needed > 0)
memcpy(self->ob_item + start * itemsize,
other->ob_item, needed * itemsize);
return 0;
}
else if (needed == 0) {
/* Delete slice */
Py_ssize_t cur, i;
if (step < 0) {
stop = start + 1;
start = stop + step * (slicelength - 1) - 1;
step = -step;
}
for (cur = start, i = 0; i < slicelength;
cur += step, i++) {
Py_ssize_t lim = step - 1;
if (cur + step >= Py_Size(self))
lim = Py_Size(self) - cur - 1;
memmove(self->ob_item + (cur - i) * itemsize,
self->ob_item + (cur + 1) * itemsize,
lim * itemsize);
}
cur = start + slicelength * step;
if (cur < Py_Size(self)) {
memmove(self->ob_item + (cur-slicelength) * itemsize,
self->ob_item + cur * itemsize,
(Py_Size(self) - cur) * itemsize);
}
if (array_resize(self, Py_Size(self) - slicelength) < 0)
return -1;
return 0;
}
else {
Py_ssize_t cur, i;
if (needed != slicelength) {
PyErr_Format(PyExc_ValueError,
"attempt to assign array of size %zd "
"to extended slice of size %zd",
needed, slicelength);
return -1;
}
for (cur = start, i = 0; i < slicelength;
cur += step, i++) {
memcpy(self->ob_item + cur * itemsize,
other->ob_item + i * itemsize,
itemsize);
}
return 0;
}
}
static PyMappingMethods array_as_mapping = {

View file

@ -138,17 +138,16 @@ static int RunModule(char *module)
fprintf(stderr, "Could not import runpy module\n");
return -1;
}
runmodule = PyObject_GetAttrString(runpy, "run_module");
runmodule = PyObject_GetAttrString(runpy, "_run_module_as_main");
if (runmodule == NULL) {
fprintf(stderr, "Could not access runpy.run_module\n");
fprintf(stderr, "Could not access runpy._run_module_as_main\n");
Py_DECREF(runpy);
return -1;
}
runargs = Py_BuildValue("sOsO", module,
Py_None, "__main__", Py_True);
runargs = Py_BuildValue("(s)", module);
if (runargs == NULL) {
fprintf(stderr,
"Could not create arguments for runpy.run_module\n");
"Could not create arguments for runpy._run_module_as_main\n");
Py_DECREF(runpy);
Py_DECREF(runmodule);
return -1;

View file

@ -659,6 +659,60 @@ mmap_slice(mmap_object *self, Py_ssize_t ilow, Py_ssize_t ihigh)
return PyBytes_FromStringAndSize(self->data + ilow, ihigh-ilow);
}
static PyObject *
mmap_subscript(mmap_object *self, PyObject *item)
{
CHECK_VALID(NULL);
if (PyIndex_Check(item)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i == -1 && PyErr_Occurred())
return NULL;
if (i < 0)
i += self->size;
if (i < 0 || i > self->size) {
PyErr_SetString(PyExc_IndexError,
"mmap index out of range");
return NULL;
}
return PyBytes_FromStringAndSize(self->data + i, 1);
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelen;
if (PySlice_GetIndicesEx((PySliceObject *)item, self->size,
&start, &stop, &step, &slicelen) < 0) {
return NULL;
}
if (slicelen <= 0)
return PyBytes_FromStringAndSize("", 0);
else if (step == 1)
return PyBytes_FromStringAndSize(self->data + start,
slicelen);
else {
char *result_buf = (char *)PyMem_Malloc(slicelen);
Py_ssize_t cur, i;
PyObject *result;
if (result_buf == NULL)
return PyErr_NoMemory();
for (cur = start, i = 0; i < slicelen;
cur += step, i++) {
result_buf[i] = self->data[cur];
}
result = PyBytes_FromStringAndSize(result_buf,
slicelen);
PyMem_Free(result_buf);
return result;
}
}
else {
PyErr_SetString(PyExc_TypeError,
"mmap indices must be integers");
return NULL;
}
}
static PyObject *
mmap_concat(mmap_object *self, PyObject *bb)
{
@ -733,7 +787,7 @@ mmap_ass_item(mmap_object *self, Py_ssize_t i, PyObject *v)
}
if (! (PyBytes_Check(v) && PyBytes_Size(v)==1) ) {
PyErr_SetString(PyExc_IndexError,
"mmap assignment must be single-character string");
"mmap assignment must be length-1 bytes()");
return -1;
}
if (!is_writeable(self))
@ -743,6 +797,96 @@ mmap_ass_item(mmap_object *self, Py_ssize_t i, PyObject *v)
return 0;
}
static int
mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value)
{
CHECK_VALID(-1);
if (PyIndex_Check(item)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
const char *buf;
if (i == -1 && PyErr_Occurred())
return -1;
if (i < 0)
i += self->size;
if (i < 0 || i > self->size) {
PyErr_SetString(PyExc_IndexError,
"mmap index out of range");
return -1;
}
if (value == NULL) {
PyErr_SetString(PyExc_TypeError,
"mmap object doesn't support item deletion");
return -1;
}
if (!PyBytes_Check(value) || PyBytes_Size(value) != 1) {
PyErr_SetString(PyExc_IndexError,
"mmap assignment must be length-1 bytes()");
return -1;
}
if (!is_writeable(self))
return -1;
buf = PyBytes_AsString(value);
self->data[i] = buf[0];
return 0;
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelen;
if (PySlice_GetIndicesEx((PySliceObject *)item,
self->size, &start, &stop,
&step, &slicelen) < 0) {
return -1;
}
if (value == NULL) {
PyErr_SetString(PyExc_TypeError,
"mmap object doesn't support slice deletion");
return -1;
}
if (!PyBytes_Check(value)) {
PyErr_SetString(PyExc_IndexError,
"mmap slice assignment must be bytes");
return -1;
}
if (PyBytes_Size(value) != slicelen) {
PyErr_SetString(PyExc_IndexError,
"mmap slice assignment is wrong size");
return -1;
}
if (!is_writeable(self))
return -1;
if (slicelen == 0)
return 0;
else if (step == 1) {
const char *buf = PyBytes_AsString(value);
if (buf == NULL)
return -1;
memcpy(self->data + start, buf, slicelen);
return 0;
}
else {
Py_ssize_t cur, i;
const char *buf = PyBytes_AsString(value);
if (buf == NULL)
return -1;
for (cur = start, i = 0; i < slicelen;
cur += step, i++) {
self->data[cur] = buf[i];
}
return 0;
}
}
else {
PyErr_SetString(PyExc_TypeError,
"mmap indices must be integer");
return -1;
}
}
static PySequenceMethods mmap_as_sequence = {
(lenfunc)mmap_length, /*sq_length*/
(binaryfunc)mmap_concat, /*sq_concat*/
@ -753,6 +897,12 @@ static PySequenceMethods mmap_as_sequence = {
(ssizessizeobjargproc)mmap_ass_slice, /*sq_ass_slice*/
};
static PyMappingMethods mmap_as_mapping = {
(lenfunc)mmap_length,
(binaryfunc)mmap_subscript,
(objobjargproc)mmap_ass_subscript,
};
static PyBufferProcs mmap_as_buffer = {
(getbufferproc)mmap_buffer_getbuf,
(releasebufferproc)mmap_buffer_releasebuf,
@ -772,7 +922,7 @@ static PyTypeObject mmap_object_type = {
0, /* tp_repr */
0, /* tp_as_number */
&mmap_as_sequence, /*tp_as_sequence*/
0, /*tp_as_mapping*/
&mmap_as_mapping, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/

View file

@ -482,6 +482,75 @@ buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
return ob;
}
static PyObject *
buffer_subscript(PyBufferObject *self, PyObject *item)
{
PyBuffer view;
PyObject *ob;
if (!get_buf(self, &view, PyBUF_SIMPLE))
return NULL;
if (PyIndex_Check(item)) {
Py_ssize_t idx = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (idx == -1 && PyErr_Occurred())
return NULL;
if (idx < 0)
idx += view.len;
if ( idx < 0 || idx >= view.len ) {
PyErr_SetString(PyExc_IndexError,
"buffer index out of range");
return NULL;
}
ob = PyBytes_FromStringAndSize((char *)view.buf + idx, 1);
PyObject_ReleaseBuffer((PyObject *)self, &view);
return ob;
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength, cur, i;
if (PySlice_GetIndicesEx((PySliceObject*)item, view.len,
&start, &stop, &step, &slicelength) < 0) {
PyObject_ReleaseBuffer((PyObject *)self, &view);
return NULL;
}
if (slicelength <= 0) {
PyObject_ReleaseBuffer((PyObject *)self, &view);
return PyBytes_FromStringAndSize("", 0);
}
else if (step == 1) {
ob = PyBytes_FromStringAndSize((char *)view.buf +
start, stop - start);
PyObject_ReleaseBuffer((PyObject *)self, &view);
return ob;
}
else {
char *source_buf = (char *)view.buf;
char *result_buf = (char *)PyMem_Malloc(slicelength);
if (result_buf == NULL)
return PyErr_NoMemory();
for (cur = start, i = 0; i < slicelength;
cur += step, i++) {
result_buf[i] = source_buf[cur];
}
ob = PyBytes_FromStringAndSize(result_buf,
slicelength);
PyMem_Free(result_buf);
PyObject_ReleaseBuffer((PyObject *)self, &view);
return ob;
}
}
else {
PyErr_SetString(PyExc_TypeError,
"sequence index must be integer");
return NULL;
}
}
static int
buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
{
@ -587,6 +656,82 @@ buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObje
return 0;
}
static int
buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
{
PyBuffer v1;
if (!get_buf(self, &v1, PyBUF_SIMPLE))
return -1;
if (self->b_readonly || v1.readonly) {
PyErr_SetString(PyExc_TypeError,
"buffer is read-only");
PyObject_ReleaseBuffer((PyObject *)self, &v1);
return -1;
}
if (PyIndex_Check(item)) {
Py_ssize_t idx = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (idx == -1 && PyErr_Occurred())
return -1;
if (idx < 0)
idx += v1.len;
PyObject_ReleaseBuffer((PyObject *)self, &v1);
return buffer_ass_item(self, idx, value);
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength;
PyBuffer v2;
PyBufferProcs *pb;
if (PySlice_GetIndicesEx((PySliceObject *)item, v1.len,
&start, &stop, &step, &slicelength) < 0) {
PyObject_ReleaseBuffer((PyObject *)self, &v1);
return -1;
}
pb = value ? value->ob_type->tp_as_buffer : NULL;
if (pb == NULL ||
pb->bf_getbuffer == NULL) {
PyObject_ReleaseBuffer((PyObject *)self, &v1);
PyErr_BadArgument();
return -1;
}
if ((*pb->bf_getbuffer)(value, &v2, PyBUF_SIMPLE) < 0) {
PyObject_ReleaseBuffer((PyObject *)self, &v1);
return -1;
}
if (v2.len != slicelength) {
PyObject_ReleaseBuffer((PyObject *)self, &v1);
PyObject_ReleaseBuffer(value, &v2);
PyErr_SetString(PyExc_TypeError, "right operand"
" length must match slice length");
return -1;
}
if (slicelength == 0)
/* nothing to do */;
else if (step == 1)
memcpy((char *)v1.buf + start, v2.buf, slicelength);
else {
Py_ssize_t cur, i;
for (cur = start, i = 0; i < slicelength;
cur += step, i++) {
((char *)v1.buf)[cur] = ((char *)v2.buf)[i];
}
}
PyObject_ReleaseBuffer((PyObject *)self, &v1);
PyObject_ReleaseBuffer(value, &v2);
return 0;
} else {
PyErr_SetString(PyExc_TypeError,
"buffer indices must be integers");
PyObject_ReleaseBuffer((PyObject *)self, &v1);
return -1;
}
}
/* Buffer methods */
static PySequenceMethods buffer_as_sequence = {
@ -599,6 +744,12 @@ static PySequenceMethods buffer_as_sequence = {
(ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
};
static PyMappingMethods buffer_as_mapping = {
(lenfunc)buffer_length,
(binaryfunc)buffer_subscript,
(objobjargproc)buffer_ass_subscript,
};
static PyBufferProcs buffer_as_buffer = {
(getbufferproc)buffer_getbuf,
(releasebufferproc)buffer_releasebuf,
@ -617,7 +768,7 @@ PyTypeObject PyBuffer_Type = {
(reprfunc)buffer_repr, /* tp_repr */
0, /* tp_as_number */
&buffer_as_sequence, /* tp_as_sequence */
0, /* tp_as_mapping */
&buffer_as_mapping, /* tp_as_mapping */
(hashfunc)buffer_hash, /* tp_hash */
0, /* tp_call */
(reprfunc)buffer_str, /* tp_str */

View file

@ -2461,6 +2461,9 @@ list_subscript(PyListObject* self, PyObject* item)
if (slicelength <= 0) {
return PyList_New(0);
}
else if (step == 1) {
return list_slice(self, start, stop);
}
else {
result = PyList_New(slicelength);
if (!result) return NULL;
@ -2504,10 +2507,15 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
return -1;
}
/* treat L[slice(a,b)] = v _exactly_ like L[a:b] = v */
if (step == 1 && ((PySliceObject*)item)->step == Py_None)
if (step == 1)
return list_ass_slice(self, start, stop, value);
/* Make sure s[5:2] = [..] inserts at the right place:
before 5, not before 2. */
if ((step < 0 && start < stop) ||
(step > 0 && start > stop))
stop = start;
if (value == NULL) {
/* delete slice */
PyObject **garbage;
@ -2529,12 +2537,16 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
return -1;
}
/* drawing pictures might help
understand these for loops */
/* drawing pictures might help understand these for
loops. Basically, we memmove the parts of the
list that are *not* part of the slice: step-1
items for each item that is part of the slice,
and then tail end of the list that was not
covered by the slice */
for (cur = start, i = 0;
cur < stop;
cur += step, i++) {
Py_ssize_t lim = step;
Py_ssize_t lim = step - 1;
garbage[i] = PyList_GET_ITEM(self, cur);
@ -2546,11 +2558,12 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
self->ob_item + cur + 1,
lim * sizeof(PyObject *));
}
for (cur = start + slicelength*step + 1;
cur < Py_Size(self); cur++) {
PyList_SET_ITEM(self, cur - slicelength,
PyList_GET_ITEM(self, cur));
cur = start + slicelength*step;
if (cur < Py_Size(self)) {
memmove(self->ob_item + cur - slicelength,
self->ob_item + cur,
(Py_Size(self) - cur) *
sizeof(PyObject *));
}
Py_Size(self) -= slicelength;
@ -2565,7 +2578,8 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
}
else {
/* assign slice */
PyObject **garbage, *ins, *seq, **seqitems, **selfitems;
PyObject *ins, *seq;
PyObject **garbage, **seqitems, **selfitems;
Py_ssize_t cur, i;
/* protect against a[::-1] = a */
@ -2575,14 +2589,17 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
}
else {
seq = PySequence_Fast(value,
"must assign iterable to extended slice");
"must assign iterable "
"to extended slice");
}
if (!seq)
return -1;
if (PySequence_Fast_GET_SIZE(seq) != slicelength) {
PyErr_Format(PyExc_ValueError,
"attempt to assign sequence of size %zd to extended slice of size %zd",
"attempt to assign sequence of "
"size %zd to extended slice of "
"size %zd",
PySequence_Fast_GET_SIZE(seq),
slicelength);
Py_DECREF(seq);

View file

@ -1146,6 +1146,17 @@ string_subscript(PyStringObject* self, PyObject* item)
if (slicelength <= 0) {
return PyString_FromStringAndSize("", 0);
}
else if (start == 0 && step == 1 &&
slicelength == PyString_GET_SIZE(self) &&
PyString_CheckExact(self)) {
Py_INCREF(self);
return (PyObject *)self;
}
else if (step == 1) {
return PyString_FromStringAndSize(
PyString_AS_STRING(self) + start,
slicelength);
}
else {
source_buf = PyString_AsString((PyObject*)self);
result_buf = (char *)PyMem_Malloc(slicelength);

View file

@ -89,6 +89,54 @@ structseq_slice(PyStructSequence *obj, Py_ssize_t low, Py_ssize_t high)
return (PyObject *) np;
}
static PyObject *
structseq_subscript(PyStructSequence *self, PyObject *item)
{
if (PyIndex_Check(item)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i == -1 && PyErr_Occurred())
return NULL;
if (i < 0)
i += VISIBLE_SIZE(self);
if (i < 0 || i >= VISIBLE_SIZE(self)) {
PyErr_SetString(PyExc_IndexError,
"tuple index out of range");
return NULL;
}
Py_INCREF(self->ob_item[i]);
return self->ob_item[i];
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelen, cur, i;
PyObject *result;
if (PySlice_GetIndicesEx((PySliceObject *)item,
VISIBLE_SIZE(self), &start, &stop,
&step, &slicelen) < 0) {
return NULL;
}
if (slicelen <= 0)
return PyTuple_New(0);
result = PyTuple_New(slicelen);
if (result == NULL)
return NULL;
for (cur = start, i = 0; i < slicelen;
cur += step, i++) {
PyObject *v = self->ob_item[cur];
Py_INCREF(v);
PyTuple_SET_ITEM(result, i, v);
}
return result;
}
else {
PyErr_SetString(PyExc_TypeError,
"structseq index must be integer");
return NULL;
}
}
static PyObject *
structseq_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
@ -298,6 +346,11 @@ static PySequenceMethods structseq_as_sequence = {
(objobjproc)structseq_contains, /* sq_contains */
};
static PyMappingMethods structseq_as_mapping = {
(lenfunc)structseq_length,
(binaryfunc)structseq_subscript,
};
static PyMethodDef structseq_methods[] = {
{"__reduce__", (PyCFunction)structseq_reduce,
METH_NOARGS, NULL},
@ -317,7 +370,7 @@ static PyTypeObject _struct_sequence_template = {
(reprfunc)structseq_repr, /* tp_repr */
0, /* tp_as_number */
&structseq_as_sequence, /* tp_as_sequence */
0, /* tp_as_mapping */
&structseq_as_mapping, /* tp_as_mapping */
structseq_hash, /* tp_hash */
0, /* tp_call */
0, /* tp_str */

View file

@ -586,6 +586,12 @@ tuplesubscript(PyTupleObject* self, PyObject* item)
if (slicelength <= 0) {
return PyTuple_New(0);
}
else if (start == 0 && step == 1 &&
slicelength == PyTuple_GET_SIZE(self) &&
PyTuple_CheckExact(self)) {
Py_INCREF(self);
return (PyObject *)self;
}
else {
result = PyTuple_New(slicelength);
if (!result) return NULL;

View file

@ -8096,6 +8096,12 @@ unicode_subscript(PyUnicodeObject* self, PyObject* item)
if (slicelength <= 0) {
return PyUnicode_FromUnicode(NULL, 0);
} else if (start == 0 && step == 1 && slicelength == self->length &&
PyUnicode_CheckExact(self)) {
Py_INCREF(self);
return (PyObject *)self;
} else if (step == 1) {
return PyUnicode_FromUnicode(self->str + start, slicelength);
} else {
source_buf = PyUnicode_AS_UNICODE((PyObject*)self);
result_buf = (Py_UNICODE *)PyMem_MALLOC(slicelength*

View file

@ -0,0 +1,79 @@
#!/usr/bin/env python
#
# fetch the certificate that the server(s) are providing in PEM form
#
# args are HOST:PORT [, HOST:PORT...]
#
# By Bill Janssen.
import sys, os
def fetch_server_certificate (host, port):
import re, tempfile, os, ssl
def subproc(cmd):
from subprocess import Popen, PIPE, STDOUT
proc = Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True)
status = proc.wait()
output = proc.stdout.read()
return status, output
def strip_to_x509_cert(certfile_contents, outfile=None):
m = re.search(r"^([-]+BEGIN CERTIFICATE[-]+[\r]*\n"
r".*[\r]*^[-]+END CERTIFICATE[-]+)$",
certfile_contents, re.MULTILINE | re.DOTALL)
if not m:
return None
else:
tn = tempfile.mktemp()
fp = open(tn, "w")
fp.write(m.group(1) + "\n")
fp.close()
try:
tn2 = (outfile or tempfile.mktemp())
status, output = subproc(r'openssl x509 -in "%s" -out "%s"' %
(tn, tn2))
if status != 0:
raise OperationError(status, tsig, output)
fp = open(tn2, 'rb')
data = fp.read()
fp.close()
os.unlink(tn2)
return data
finally:
os.unlink(tn)
if sys.platform.startswith("win"):
tfile = tempfile.mktemp()
fp = open(tfile, "w")
fp.write("quit\n")
fp.close()
try:
status, output = subproc(
'openssl s_client -connect "%s:%s" -showcerts < "%s"' %
(host, port, tfile))
finally:
os.unlink(tfile)
else:
status, output = subproc(
'openssl s_client -connect "%s:%s" -showcerts < /dev/null' %
(host, port))
if status != 0:
raise OSError(status)
certtext = strip_to_x509_cert(output)
if not certtext:
raise ValueError("Invalid response received from server at %s:%s" %
(host, port))
return certtext
if __name__ == "__main__":
if len(sys.argv) < 2:
sys.stderr.write(
"Usage: %s HOSTNAME:PORTNUMBER [, HOSTNAME:PORTNUMBER...]\n" %
sys.argv[0])
sys.exit(1)
for arg in sys.argv[1:]:
host, port = arg.split(":")
sys.stdout.write(fetch_server_certificate(host, int(port)))
sys.exit(0)

View file

@ -618,6 +618,7 @@ def detect_modules(self):
exts.append( Extension('_sha256', ['sha256module.c']) )
exts.append( Extension('_sha512', ['sha512module.c']) )
else:
# these aren't strictly missing since they are unneeded.
missing.extend(['_sha256', '_sha512'])
# Modules that provide persistent dictionary-like semantics. You will
@ -627,9 +628,9 @@ def detect_modules(self):
# implementation independent wrapper for these; dumbdbm.py provides
# similar functionality (but slower of course) implemented in Python.
# Sleepycat Berkeley DB interface. http://www.sleepycat.com
# Sleepycat^WOracle Berkeley DB interface. http://www.sleepycat.com
#
# This requires the Sleepycat DB code. The supported versions
# This requires the Sleepycat^WOracle DB code. The supported versions
# are set below. Visit http://www.sleepycat.com/ to download
# a release. Most open source OSes come with one or more
# versions of BerkeleyDB already installed.