[Python-checkins] r55977 - in python/branches/cpy_merge: Lib/_abcoll.py Lib/abc.py Lib/test/test_abc.py Lib/test/test_super.py Lib/test/test_urllib2_localnet.py Tools/buildbot/build-amd64.bat Tools/buildbot/clean-amd64.bat Tools/buildbot/external-amd64.bat Tools/buildbot/test-amd64.bat

alexandre.vassalotti python-checkins at python.org
Thu Jun 14 23:10:26 CEST 2007


Author: alexandre.vassalotti
Date: Thu Jun 14 23:10:12 2007
New Revision: 55977

Added:
   python/branches/cpy_merge/Lib/_abcoll.py
   python/branches/cpy_merge/Lib/abc.py
   python/branches/cpy_merge/Lib/test/test_abc.py
   python/branches/cpy_merge/Lib/test/test_super.py
   python/branches/cpy_merge/Lib/test/test_urllib2_localnet.py
   python/branches/cpy_merge/Tools/buildbot/build-amd64.bat
   python/branches/cpy_merge/Tools/buildbot/clean-amd64.bat
   python/branches/cpy_merge/Tools/buildbot/external-amd64.bat
   python/branches/cpy_merge/Tools/buildbot/test-amd64.bat
Log:
Add new files from the merge in r55972.


Added: python/branches/cpy_merge/Lib/_abcoll.py
==============================================================================
--- (empty file)
+++ python/branches/cpy_merge/Lib/_abcoll.py	Thu Jun 14 23:10:12 2007
@@ -0,0 +1,535 @@
+# Copyright 2007 Google, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+"""Abstract Base Classes (ABCs) for collections, according to PEP 3119.
+
+DON'T USE THIS MODULE DIRECTLY!  The classes here should be imported
+via collections; they are defined here only to alleviate ceratin
+bootstrapping issues.  Unit tests are in test_collections.
+"""
+
+from abc import ABCMeta, abstractmethod
+
+__all__ = ["Hashable", "Iterable", "Iterator",
+           "Sized", "Container", "Callable",
+           "Set", "MutableSet",
+           "Mapping", "MutableMapping",
+           "MappingView", "KeysView", "ItemsView", "ValuesView",
+           "Sequence", "MutableSequence",
+           ]
+
+### ONE-TRICK PONIES ###
+
+class Hashable(metaclass=ABCMeta):
+
+    @abstractmethod
+    def __hash__(self):
+        return 0
+
+    @classmethod
+    def __subclasshook__(cls, C):
+        if cls is Hashable:
+            for B in C.__mro__:
+                if "__hash__" in B.__dict__:
+                    if B.__dict__["__hash__"]:
+                        return True
+                    break
+        return NotImplemented
+
+
+class Iterable(metaclass=ABCMeta):
+
+    @abstractmethod
+    def __iter__(self):
+        while False:
+            yield None
+
+    @classmethod
+    def __subclasshook__(cls, C):
+        if cls is Iterable:
+            if any("__iter__" in B.__dict__ for B in C.__mro__):
+                return True
+        return NotImplemented
+
+Iterable.register(bytes)
+
+
+class Iterator(metaclass=ABCMeta):
+
+    @abstractmethod
+    def __next__(self):
+        raise StopIteration
+
+    def __iter__(self):
+        return self
+
+    @classmethod
+    def __subclasshook__(cls, C):
+        if cls is Iterator:
+            if any("__next__" in B.__dict__ for B in C.__mro__):
+                return True
+        return NotImplemented
+
+
+class Sized(metaclass=ABCMeta):
+
+    @abstractmethod
+    def __len__(self):
+        return 0
+
+    @classmethod
+    def __subclasshook__(cls, C):
+        if cls is Sized:
+            if any("__len__" in B.__dict__ for B in C.__mro__):
+                return True
+        return NotImplemented
+
+
+class Container(metaclass=ABCMeta):
+
+    @abstractmethod
+    def __contains__(self, x):
+        return False
+
+    @classmethod
+    def __subclasshook__(cls, C):
+        if cls is Container:
+            if any("__contains__" in B.__dict__ for B in C.__mro__):
+                return True
+        return NotImplemented
+
+
+class Callable(metaclass=ABCMeta):
+
+    @abstractmethod
+    def __contains__(self, x):
+        return False
+
+    @classmethod
+    def __subclasshook__(cls, C):
+        if cls is Callable:
+            if any("__call__" in B.__dict__ for B in C.__mro__):
+                return True
+        return NotImplemented
+
+
+### SETS ###
+
+
+class Set(metaclass=ABCMeta):
+
+    """A set is a finite, iterable container.
+
+    This class provides concrete generic implementations of all
+    methods except for __contains__, __iter__ and __len__.
+
+    To override the comparisons (presumably for speed, as the
+    semantics are fixed), all you have to do is redefine __le__ and
+    then the other operations will automatically follow suit.
+    """
+
+    @abstractmethod
+    def __contains__(self, value):
+        return False
+
+    @abstractmethod
+    def __iter__(self):
+        while False:
+            yield None
+
+    @abstractmethod
+    def __len__(self):
+        return 0
+
+    def __le__(self, other):
+        if not isinstance(other, Set):
+            return NotImplemented
+        if len(self) > len(other):
+            return False
+        for elem in self:
+            if elem not in other:
+                return False
+        return True
+
+    def __lt__(self, other):
+        if not isinstance(other, Set):
+            return NotImplemented
+        return len(self) < len(other) and self.__le__(other)
+
+    def __eq__(self, other):
+        if not isinstance(other, Set):
+            return NotImplemented
+        return len(self) == len(other) and self.__le__(other)
+
+    @classmethod
+    def _from_iterable(cls, it):
+        return frozenset(it)
+
+    def __and__(self, other):
+        if not isinstance(other, Iterable):
+            return NotImplemented
+        return self._from_iterable(value for value in other if value in self)
+
+    def __or__(self, other):
+        if not isinstance(other, Iterable):
+            return NotImplemented
+        return self._from_iterable(itertools.chain(self, other))
+
+    def __sub__(self, other):
+        if not isinstance(other, Set):
+            if not isinstance(other, Iterable):
+                return NotImplemented
+            other = self._from_iterable(other)
+        return self._from_iterable(value for value in self
+                                   if value not in other)
+
+    def __xor__(self, other):
+        if not isinstance(other, Set):
+            if not isinstance(other, Iterable):
+                return NotImplemented
+            other = self._from_iterable(other)
+        return (self - other) | (other - self)
+
+    def _hash(self):
+        """Compute the hash value of a set.
+
+        Note that we don't define __hash__: not all sets are hashable.
+        But if you define a hashable set type, its __hash__ should
+        call this function.
+
+        This must be compatible __eq__.
+
+        All sets ought to compare equal if they contain the same
+        elements, regardless of how they are implemented, and
+        regardless of the order of the elements; so there's not much
+        freedom for __eq__ or __hash__.  We match the algorithm used
+        by the built-in frozenset type.
+        """
+        MAX = sys.maxint
+        MASK = 2 * MAX + 1
+        n = len(self)
+        h = 1927868237 * (n + 1)
+        h &= MASK
+        for x in self:
+            hx = hash(x)
+            h ^= (hx ^ (hx << 16) ^ 89869747)  * 3644798167
+            h &= MASK
+        h = h * 69069 + 907133923
+        h &= MASK
+        if h > MAX:
+            h -= MASK + 1
+        if h == -1:
+            h = 590923713
+        return h
+
+Set.register(frozenset)
+
+
+class MutableSet(Set):
+
+    @abstractmethod
+    def add(self, value):
+        """Return True if it was added, False if already there."""
+        raise NotImplementedError
+
+    @abstractmethod
+    def discard(self, value):
+        """Return True if it was deleted, False if not there."""
+        raise NotImplementedError
+
+    def pop(self):
+        """Return the popped value.  Raise KeyError if empty."""
+        it = iter(self)
+        try:
+            value = it.__next__()
+        except StopIteration:
+            raise KeyError
+        self.discard(value)
+        return value
+
+    def toggle(self, value):
+        """Return True if it was added, False if deleted."""
+        # XXX This implementation is not thread-safe
+        if value in self:
+            self.discard(value)
+            return False
+        else:
+            self.add(value)
+            return True
+
+    def clear(self):
+        """This is slow (creates N new iterators!) but effective."""
+        try:
+            while True:
+                self.pop()
+        except KeyError:
+            pass
+
+    def __ior__(self, it: Iterable):
+        for value in it:
+            self.add(value)
+        return self
+
+    def __iand__(self, c: Container):
+        for value in self:
+            if value not in c:
+                self.discard(value)
+        return self
+
+    def __ixor__(self, it: Iterable):
+        # This calls toggle(), so if that is overridded, we call the override
+        for value in it:
+            self.toggle(it)
+        return self
+
+    def __isub__(self, it: Iterable):
+        for value in it:
+            self.discard(value)
+        return self
+
+MutableSet.register(set)
+
+
+### MAPPINGS ###
+
+
+class Mapping(metaclass=ABCMeta):
+
+    @abstractmethod
+    def __getitem__(self, key):
+        raise KeyError
+
+    def get(self, key, default=None):
+        try:
+            return self[key]
+        except KeyError:
+            return default
+
+    def __contains__(self, key):
+        try:
+            self[key]
+        except KeyError:
+            return False
+        else:
+            return True
+
+    @abstractmethod
+    def __len__(self):
+        return 0
+
+    @abstractmethod
+    def __iter__(self):
+        while False:
+            yield None
+
+    def keys(self):
+        return KeysView(self)
+
+    def items(self):
+        return ItemsView(self)
+
+    def values(self):
+        return ValuesView(self)
+
+
+class MappingView(metaclass=ABCMeta):
+
+    def __init__(self, mapping):
+        self._mapping = mapping
+
+    def __len__(self):
+        return len(self._mapping)
+
+
+class KeysView(MappingView, Set):
+
+    def __contains__(self, key):
+        return key in self._mapping
+
+    def __iter__(self):
+        for key in self._mapping:
+            yield key
+
+KeysView.register(type({}.keys()))
+
+
+class ItemsView(MappingView, Set):
+
+    def __contains__(self, item):
+        key, value = item
+        try:
+            v = self._mapping[key]
+        except KeyError:
+            return False
+        else:
+            return v == value
+
+    def __iter__(self):
+        for key in self._mapping:
+            yield (key, self._mapping[key])
+
+ItemsView.register(type({}.items()))
+
+
+class ValuesView(MappingView):
+
+    def __contains__(self, value):
+        for key in self._mapping:
+            if value == self._mapping[key]:
+                return True
+        return False
+
+    def __iter__(self):
+        for key in self._mapping:
+            yield self._mapping[key]
+
+ValuesView.register(type({}.values()))
+
+
+class MutableMapping(Mapping):
+
+    @abstractmethod
+    def __setitem__(self, key, value):
+        raise KeyError
+
+    @abstractmethod
+    def __delitem__(self, key):
+        raise KeyError
+
+    __marker = object()
+
+    def pop(self, key, default=__marker):
+        try:
+            value = self[key]
+        except KeyError:
+            if default is self.__marker:
+                raise
+            return default
+        else:
+            del self[key]
+            return value
+
+    def popitem(self):
+        try:
+            key = next(iter(self))
+        except StopIteration:
+            raise KeyError
+        value = self[key]
+        del self[key]
+        return key, value
+
+    def clear(self):
+        try:
+            while True:
+                self.popitem()
+        except KeyError:
+            pass
+
+    def update(self, other=(), **kwds):
+        if isinstance(other, Mapping):
+            for key in other:
+                self[key] = other[key]
+        elif hasattr(other, "keys"):
+            for key in other.keys():
+                self[key] = other[key]
+        else:
+            for key, value in other:
+                self[key] = value
+        for key, value in kwds.items():
+            self[key] = value
+
+MutableMapping.register(dict)
+
+
+### SEQUENCES ###
+
+
+class Sequence(metaclass=ABCMeta):
+
+    """All the operations on a read-only sequence.
+
+    Concrete subclasses must override __new__ or __init__,
+    __getitem__, and __len__.
+    """
+
+    @abstractmethod
+    def __getitem__(self, index):
+        raise IndexError
+
+    @abstractmethod
+    def __len__(self):
+        return 0
+
+    def __iter__(self):
+        i = 0
+        while True:
+            try:
+                v = self[i]
+            except IndexError:
+                break
+            yield v
+            i += 1
+
+    def __contains__(self, value):
+        for v in self:
+            if v == value:
+                return True
+        return False
+
+    def __reversed__(self):
+        for i in reversed(range(len(self))):
+            yield self[i]
+
+    def index(self, value):
+        for i, v in enumerate(self):
+            if v == value:
+                return i
+        raise ValueError
+
+    def count(self, value):
+        return sum(1 for v in self if v == value)
+
+Sequence.register(tuple)
+Sequence.register(basestring)
+Sequence.register(buffer)
+
+
+class MutableSequence(Sequence):
+
+    @abstractmethod
+    def __setitem__(self, index, value):
+        raise IndexError
+
+    @abstractmethod
+    def __delitem__(self, index):
+        raise IndexError
+
+    @abstractmethod
+    def insert(self, index, value):
+        raise IndexError
+
+    def append(self, value):
+        self.insert(len(self), value)
+
+    def reverse(self):
+        n = len(self)
+        for i in range(n//2):
+            self[i], self[n-i-1] = self[n-i-1], self[i]
+
+    def extend(self, values):
+        for v in values:
+            self.append(v)
+
+    def pop(self, index=-1):
+        v = self[index]
+        del self[index]
+        return v
+
+    def remove(self, value):
+        del self[self.index(value)]
+
+    def __iadd__(self, values):
+        self.extend(values)
+
+MutableSequence.register(list)
+MutableSequence.register(bytes)

Added: python/branches/cpy_merge/Lib/abc.py
==============================================================================
--- (empty file)
+++ python/branches/cpy_merge/Lib/abc.py	Thu Jun 14 23:10:12 2007
@@ -0,0 +1,179 @@
+# Copyright 2007 Google, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+"""Abstract Base Classes (ABCs) according to PEP 3119."""
+
+
+def abstractmethod(funcobj):
+    """A decorator indicating abstract methods.
+
+    Requires that the metaclass is ABCMeta or derived from it.  A
+    class that has a metaclass derived from ABCMeta cannot be
+    instantiated unless all of its abstract methods are overridden.
+    The abstract methods can be called using any of the the normal
+    'super' call mechanisms.
+
+    Usage:
+
+        class C(metaclass=ABCMeta):
+            @abstractmethod
+            def my_abstract_method(self, ...):
+                ...
+    """
+    funcobj.__isabstractmethod__ = True
+    return funcobj
+
+
+class _Abstract(object):
+
+    """Helper class inserted into the bases by ABCMeta (using _fix_bases()).
+
+    You should never need to explicitly subclass this class.
+
+    There should never be a base class between _Abstract and object.
+    """
+
+    def __new__(cls, *args, **kwds):
+        am = cls.__dict__.get("__abstractmethods__")
+        if am:
+            raise TypeError("Can't instantiate abstract class %s "
+                            "with abstract methods %s" %
+                            (cls.__name__, ", ".join(sorted(am))))
+        if (args or kwds) and cls.__init__ is object.__init__:
+            raise TypeError("Can't pass arguments to __new__ "
+                            "without overriding __init__")
+        return object.__new__(cls)
+
+    @classmethod
+    def __subclasshook__(cls, subclass):
+        """Abstract classes can override this to customize issubclass().
+
+        This is invoked early on by __subclasscheck__() below.  It
+        should return True, False or NotImplemented.  If it returns
+        NotImplemented, the normal algorithm is used.  Otherwise, it
+        overrides the normal algorithm (and the outcome is cached).
+        """
+        return NotImplemented
+
+
+def _fix_bases(bases):
+    """Helper method that inserts _Abstract in the bases if needed."""
+    for base in bases:
+        if issubclass(base, _Abstract):
+            # _Abstract is already a base (maybe indirectly)
+            return bases
+    if object in bases:
+        # Replace object with _Abstract
+        return tuple([_Abstract if base is object else base
+                      for base in bases])
+    # Append _Abstract to the end
+    return bases + (_Abstract,)
+
+
+class ABCMeta(type):
+
+    """Metaclass for defining Abstract Base Classes (ABCs).
+
+    Use this metaclass to create an ABC.  An ABC can be subclassed
+    directly, and then acts as a mix-in class.  You can also register
+    unrelated concrete classes (even built-in classes) and unrelated
+    ABCs as 'virtual subclasses' -- these and their descendants will
+    be considered subclasses of the registering ABC by the built-in
+    issubclass() function, but the registering ABC won't show up in
+    their MRO (Method Resolution Order) nor will method
+    implementations defined by the registering ABC be callable (not
+    even via super()).
+
+    """
+
+    # A global counter that is incremented each time a class is
+    # registered as a virtual subclass of anything.  It forces the
+    # negative cache to be cleared before its next use.
+    __invalidation_counter = 0
+
+    def __new__(mcls, name, bases, namespace):
+        bases = _fix_bases(bases)
+        cls = super().__new__(mcls, name, bases, namespace)
+        # Compute set of abstract method names
+        abstracts = {name
+                     for name, value in namespace.items()
+                     if getattr(value, "__isabstractmethod__", False)}
+        for base in bases:
+            for name in getattr(base, "__abstractmethods__", set()):
+                value = getattr(cls, name, None)
+                if getattr(value, "__isabstractmethod__", False):
+                    abstracts.add(name)
+        cls.__abstractmethods__ = abstracts
+        # Set up inheritance registry
+        cls.__registry = set()
+        cls.__cache = set()
+        cls.__negative_cache = set()
+        cls.__negative_cache_version = ABCMeta.__invalidation_counter
+        return cls
+
+    def register(cls, subclass):
+        """Register a virtual subclass of an ABC."""
+        if not isinstance(cls, type):
+            raise TypeError("Can only register classes")
+        if issubclass(subclass, cls):
+            return  # Already a subclass
+        # Subtle: test for cycles *after* testing for "already a subclass";
+        # this means we allow X.register(X) and interpret it as a no-op.
+        if issubclass(cls, subclass):
+            # This would create a cycle, which is bad for the algorithm below
+            raise RuntimeError("Refusing to create an inheritance cycle")
+        cls.__registry.add(subclass)
+        ABCMeta.__invalidation_counter += 1  # Invalidate negative cache
+
+    def _dump_registry(cls, file=None):
+        """Debug helper to print the ABC registry."""
+        print("Class: %s.%s" % (cls.__module__, cls.__name__), file=file)
+        print("Inv.counter: %s" % ABCMeta.__invalidation_counter, file=file)
+        for name in sorted(cls.__dict__.keys()):
+            if name.startswith("__abc_"):
+                value = getattr(cls, name)
+                print("%s: %r" % (name, value), file=file)
+
+    def __instancecheck__(cls, instance):
+        """Override for isinstance(instance, cls)."""
+        return any(cls.__subclasscheck__(c)
+                   for c in {instance.__class__, type(instance)})
+
+    def __subclasscheck__(cls, subclass):
+        """Override for issubclass(subclass, cls)."""
+        # Check cache
+        if subclass in cls.__cache:
+            return True
+        # Check negative cache; may have to invalidate
+        if cls.__negative_cache_version < ABCMeta.__invalidation_counter:
+            # Invalidate the negative cache
+            cls.__negative_cache_version = ABCMeta.__invalidation_counter
+            cls.__negative_cache = set()
+        elif subclass in cls.__negative_cache:
+            return False
+        # Check the subclass hook
+        ok = cls.__subclasshook__(subclass)
+        if ok is not NotImplemented:
+            assert isinstance(ok, bool)
+            if ok:
+                cls.__cache.add(subclass)
+            else:
+                cls.__negative_cache.add(subclass)
+            return ok
+        # Check if it's a direct subclass
+        if cls in subclass.__mro__:
+            cls.__cache.add(subclass)
+            return True
+        # Check if it's a subclass of a registered class (recursive)
+        for rcls in cls.__registry:
+            if issubclass(subclass, rcls):
+                cls.__registry.add(subclass)
+                return True
+        # Check if it's a subclass of a subclass (recursive)
+        for scls in cls.__subclasses__():
+            if issubclass(subclass, scls):
+                cls.__registry.add(subclass)
+                return True
+        # No dice; update negative cache
+        cls.__negative_cache.add(subclass)
+        return False

Added: python/branches/cpy_merge/Lib/test/test_abc.py
==============================================================================
--- (empty file)
+++ python/branches/cpy_merge/Lib/test/test_abc.py	Thu Jun 14 23:10:12 2007
@@ -0,0 +1,123 @@
+# Copyright 2007 Google, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+"""Unit tests for abc.py."""
+
+import sys
+import unittest
+from test import test_support
+
+import abc
+
+
+class TestABC(unittest.TestCase):
+
+    def test_abstractmethod_basics(self):
+        @abc.abstractmethod
+        def foo(self): pass
+        self.assertEqual(foo.__isabstractmethod__, True)
+        def bar(self): pass
+        self.assertEqual(hasattr(bar, "__isabstractmethod__"), False)
+
+    def test_abstractmethod_integration(self):
+        class C(metaclass=abc.ABCMeta):
+            @abc.abstractmethod
+            def foo(self): pass  # abstract
+            def bar(self): pass  # concrete
+        self.assertEqual(C.__abstractmethods__, {"foo"})
+        self.assertRaises(TypeError, C)  # because foo is abstract
+        class D(C):
+            def bar(self): pass  # concrete override of concrete
+        self.assertEqual(D.__abstractmethods__, {"foo"})
+        self.assertRaises(TypeError, D)  # because foo is still abstract
+        class E(D):
+            def foo(self): pass
+        self.assertEqual(E.__abstractmethods__, set())
+        E()  # now foo is concrete, too
+        class F(E):
+            @abc.abstractmethod
+            def bar(self): pass  # abstract override of concrete
+        self.assertEqual(F.__abstractmethods__, {"bar"})
+        self.assertRaises(TypeError, F)  # because bar is abstract now
+
+    def test_registration_basics(self):
+        class A(metaclass=abc.ABCMeta):
+            pass
+        class B:
+            pass
+        b = B()
+        self.assertEqual(issubclass(B, A), False)
+        self.assertEqual(isinstance(b, A), False)
+        A.register(B)
+        self.assertEqual(issubclass(B, A), True)
+        self.assertEqual(isinstance(b, A), True)
+        class C(B):
+            pass
+        c = C()
+        self.assertEqual(issubclass(C, A), True)
+        self.assertEqual(isinstance(c, A), True)
+
+    def test_registration_builtins(self):
+        class A(metaclass=abc.ABCMeta):
+            pass
+        A.register(int)
+        self.assertEqual(isinstance(42, A), True)
+        self.assertEqual(issubclass(int, A), True)
+        class B(A):
+            pass
+        B.register(basestring)
+        self.assertEqual(isinstance("", A), True)
+        self.assertEqual(issubclass(str, A), True)
+
+    def test_registration_edge_cases(self):
+        class A(metaclass=abc.ABCMeta):
+            pass
+        A.register(A)  # should pass silently
+        class A1(A):
+            pass
+        self.assertRaises(RuntimeError, A1.register, A)  # cycles not allowed
+        class B:
+            pass
+        A1.register(B)  # ok
+        A1.register(B)  # should pass silently
+        class C(A):
+            pass
+        A.register(C)  # should pass silently
+        self.assertRaises(RuntimeError, C.register, A)  # cycles not allowed
+        C.register(B)  # ok
+
+    def test_registration_transitiveness(self):
+        class A(metaclass=abc.ABCMeta):
+            pass
+        self.failUnless(issubclass(A, A))
+        class B(metaclass=abc.ABCMeta):
+            pass
+        self.failIf(issubclass(A, B))
+        self.failIf(issubclass(B, A))
+        class C(metaclass=abc.ABCMeta):
+            pass
+        A.register(B)
+        class B1(B):
+            pass
+        self.failUnless(issubclass(B1, A))
+        class C1(C):
+            pass
+        B1.register(C1)
+        self.failIf(issubclass(C, B))
+        self.failIf(issubclass(C, B1))
+        self.failUnless(issubclass(C1, A))
+        self.failUnless(issubclass(C1, B))
+        self.failUnless(issubclass(C1, B1))
+        C1.register(int)
+        class MyInt(int):
+            pass
+        self.failUnless(issubclass(MyInt, A))
+        self.failUnless(isinstance(42, A))
+
+
+def test_main():
+    test_support.run_unittest(TestABC)
+
+
+if __name__ == "__main__":
+    unittest.main()

Added: python/branches/cpy_merge/Lib/test/test_super.py
==============================================================================
--- (empty file)
+++ python/branches/cpy_merge/Lib/test/test_super.py	Thu Jun 14 23:10:12 2007
@@ -0,0 +1,79 @@
+"""Unit tests for new super() implementation."""
+
+import sys
+import unittest
+from test import test_support
+
+
+class A:
+    def f(self):
+        return 'A'
+    @classmethod
+    def cm(cls):
+        return (cls, 'A')
+
+class B(A):
+    def f(self):
+        return super().f() + 'B'
+    @classmethod
+    def cm(cls):
+        return (cls, super().cm(), 'B')
+
+class C(A):
+    def f(self):
+        return super().f() + 'C'
+    @classmethod
+    def cm(cls):
+        return (cls, super().cm(), 'C')
+
+class D(C, B):
+    def f(self):
+        return super().f() + 'D'
+    def cm(cls):
+        return (cls, super().cm(), 'D')
+
+class E(D):
+    pass
+
+class F(E):
+    f = E.f
+
+class G(A):
+    pass
+
+
+class TestSuper(unittest.TestCase):
+
+    def testBasicsWorking(self):
+        self.assertEqual(D().f(), 'ABCD')
+
+    def testClassGetattrWorking(self):
+        self.assertEqual(D.f(D()), 'ABCD')
+
+    def testSubclassNoOverrideWorking(self):
+        self.assertEqual(E().f(), 'ABCD')
+        self.assertEqual(E.f(E()), 'ABCD')
+
+    def testUnboundMethodTransferWorking(self):
+        self.assertEqual(F().f(), 'ABCD')
+        self.assertEqual(F.f(F()), 'ABCD')
+
+    def testClassMethodsStillWorking(self):
+        self.assertEqual(A.cm(), (A, 'A'))
+        self.assertEqual(A().cm(), (A, 'A'))
+        self.assertEqual(G.cm(), (G, 'A'))
+        self.assertEqual(G().cm(), (G, 'A'))
+
+    def testSuperInClassMethodsWorking(self):
+        d = D()
+        self.assertEqual(d.cm(), (d, (D, (D, (D, 'A'), 'B'), 'C'), 'D'))
+        e = E()
+        self.assertEqual(e.cm(), (e, (E, (E, (E, 'A'), 'B'), 'C'), 'D'))
+
+
+def test_main():
+    test_support.run_unittest(TestSuper)
+
+
+if __name__ == "__main__":
+    unittest.main()

Added: python/branches/cpy_merge/Lib/test/test_urllib2_localnet.py
==============================================================================
--- (empty file)
+++ python/branches/cpy_merge/Lib/test/test_urllib2_localnet.py	Thu Jun 14 23:10:12 2007
@@ -0,0 +1,310 @@
+#!/usr/bin/env python
+
+import sys
+import threading
+import urlparse
+import urllib2
+import BaseHTTPServer
+import unittest
+import hashlib
+from test import test_support
+
+# Loopback http server infrastructure
+
+class LoopbackHttpServer(BaseHTTPServer.HTTPServer):
+    """HTTP server w/ a few modifications that make it useful for
+    loopback testing purposes.
+    """
+
+    def __init__(self, server_address, RequestHandlerClass):
+        BaseHTTPServer.HTTPServer.__init__(self,
+                                           server_address,
+                                           RequestHandlerClass)
+
+        # Set the timeout of our listening socket really low so
+        # that we can stop the server easily.
+        self.socket.settimeout(1.0)
+
+    def get_request(self):
+        """BaseHTTPServer method, overridden."""
+
+        request, client_address = self.socket.accept()
+
+        # It's a loopback connection, so setting the timeout
+        # really low shouldn't affect anything, but should make
+        # deadlocks less likely to occur.
+        request.settimeout(10.0)
+
+        return (request, client_address)
+
+class LoopbackHttpServerThread(threading.Thread):
+    """Stoppable thread that runs a loopback http server."""
+
+    def __init__(self, port, RequestHandlerClass):
+        threading.Thread.__init__(self)
+        self._RequestHandlerClass = RequestHandlerClass
+        self._stop = False
+        self._port = port
+        self._server_address = ('127.0.0.1', self._port)
+        self.ready = threading.Event()
+        self.error = None
+
+    def stop(self):
+        """Stops the webserver if it's currently running."""
+
+        # Set the stop flag.
+        self._stop = True
+
+        self.join()
+
+    def run(self):
+        protocol = "HTTP/1.0"
+
+        try:
+            self._RequestHandlerClass.protocol_version = protocol
+            httpd = LoopbackHttpServer(self._server_address,
+                                       self._RequestHandlerClass)
+
+            sa = httpd.socket.getsockname()
+            #print "Serving HTTP on", sa[0], "port", sa[1], "..."
+        except:
+            # Fail "gracefully" if we are unable to start.
+            self.ready.set()
+            self.error = sys.exc_info()[1]
+            raise
+
+        self.ready.set()
+        while not self._stop:
+            httpd.handle_request()
+
+# Authentication infrastructure
+
+class DigestAuthHandler:
+    """Handler for performing digest authentication."""
+
+    def __init__(self):
+        self._request_num = 0
+        self._nonces = []
+        self._users = {}
+        self._realm_name = "Test Realm"
+        self._qop = "auth"
+
+    def set_qop(self, qop):
+        self._qop = qop
+
+    def set_users(self, users):
+        assert isinstance(users, dict)
+        self._users = users
+
+    def set_realm(self, realm):
+        self._realm_name = realm
+
+    def _generate_nonce(self):
+        self._request_num += 1
+        nonce = hashlib.md5(str(self._request_num)).hexdigest()
+        self._nonces.append(nonce)
+        return nonce
+
+    def _create_auth_dict(self, auth_str):
+        first_space_index = auth_str.find(" ")
+        auth_str = auth_str[first_space_index+1:]
+
+        parts = auth_str.split(",")
+
+        auth_dict = {}
+        for part in parts:
+            name, value = part.split("=")
+            name = name.strip()
+            if value[0] == '"' and value[-1] == '"':
+                value = value[1:-1]
+            else:
+                value = value.strip()
+            auth_dict[name] = value
+        return auth_dict
+
+    def _validate_auth(self, auth_dict, password, method, uri):
+        final_dict = {}
+        final_dict.update(auth_dict)
+        final_dict["password"] = password
+        final_dict["method"] = method
+        final_dict["uri"] = uri
+        HA1_str = "%(username)s:%(realm)s:%(password)s" % final_dict
+        HA1 = hashlib.md5(HA1_str).hexdigest()
+        HA2_str = "%(method)s:%(uri)s" % final_dict
+        HA2 = hashlib.md5(HA2_str).hexdigest()
+        final_dict["HA1"] = HA1
+        final_dict["HA2"] = HA2
+        response_str = "%(HA1)s:%(nonce)s:%(nc)s:" \
+                       "%(cnonce)s:%(qop)s:%(HA2)s" % final_dict
+        response = hashlib.md5(response_str).hexdigest()
+
+        return response == auth_dict["response"]
+
+    def _return_auth_challenge(self, request_handler):
+        request_handler.send_response(407, "Proxy Authentication Required")
+        request_handler.send_header("Content-Type", "text/html")
+        request_handler.send_header(
+            'Proxy-Authenticate', 'Digest realm="%s", '
+            'qop="%s",'
+            'nonce="%s", ' % \
+            (self._realm_name, self._qop, self._generate_nonce()))
+        # XXX: Not sure if we're supposed to add this next header or
+        # not.
+        #request_handler.send_header('Connection', 'close')
+        request_handler.end_headers()
+        request_handler.wfile.write("Proxy Authentication Required.")
+        return False
+
+    def handle_request(self, request_handler):
+        """Performs digest authentication on the given HTTP request
+        handler.  Returns True if authentication was successful, False
+        otherwise.
+
+        If no users have been set, then digest auth is effectively
+        disabled and this method will always return True.
+        """
+
+        if len(self._users) == 0:
+            return True
+
+        if 'Proxy-Authorization' not in request_handler.headers:
+            return self._return_auth_challenge(request_handler)
+        else:
+            auth_dict = self._create_auth_dict(
+                request_handler.headers['Proxy-Authorization']
+                )
+            if auth_dict["username"] in self._users:
+                password = self._users[ auth_dict["username"] ]
+            else:
+                return self._return_auth_challenge(request_handler)
+            if not auth_dict.get("nonce") in self._nonces:
+                return self._return_auth_challenge(request_handler)
+            else:
+                self._nonces.remove(auth_dict["nonce"])
+
+            auth_validated = False
+
+            # MSIE uses short_path in its validation, but Python's
+            # urllib2 uses the full path, so we're going to see if
+            # either of them works here.
+
+            for path in [request_handler.path, request_handler.short_path]:
+                if self._validate_auth(auth_dict,
+                                       password,
+                                       request_handler.command,
+                                       path):
+                    auth_validated = True
+
+            if not auth_validated:
+                return self._return_auth_challenge(request_handler)
+            return True
+
+# Proxy test infrastructure
+
+class FakeProxyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
+    """This is a 'fake proxy' that makes it look like the entire
+    internet has gone down due to a sudden zombie invasion.  It main
+    utility is in providing us with authentication support for
+    testing.
+    """
+
+    digest_auth_handler = DigestAuthHandler()
+
+    def log_message(self, format, *args):
+        # Uncomment the next line for debugging.
+        #sys.stderr.write(format % args)
+        pass
+
+    def do_GET(self):
+        (scm, netloc, path, params, query, fragment) = urlparse.urlparse(
+            self.path, 'http')
+        self.short_path = path
+        if self.digest_auth_handler.handle_request(self):
+            self.send_response(200, "OK")
+            self.send_header("Content-Type", "text/html")
+            self.end_headers()
+            self.wfile.write("You've reached %s!<BR>" % self.path)
+            self.wfile.write("Our apologies, but our server is down due to "
+                              "a sudden zombie invasion.")
+
+# Test cases
+
+class ProxyAuthTests(unittest.TestCase):
+    URL = "http://www.foo.com"
+
+    PORT = 8080
+    USER = "tester"
+    PASSWD = "test123"
+    REALM = "TestRealm"
+
+    PROXY_URL = "http://127.0.0.1:%d" % PORT
+
+    def setUp(self):
+        FakeProxyHandler.digest_auth_handler.set_users({
+            self.USER : self.PASSWD
+            })
+        FakeProxyHandler.digest_auth_handler.set_realm(self.REALM)
+
+        self.server = LoopbackHttpServerThread(self.PORT, FakeProxyHandler)
+        self.server.start()
+        self.server.ready.wait()
+        if self.server.error:
+            raise self.server.error
+
+        handler = urllib2.ProxyHandler({"http" : self.PROXY_URL})
+        self._digest_auth_handler = urllib2.ProxyDigestAuthHandler()
+        self.opener = urllib2.build_opener(handler, self._digest_auth_handler)
+
+    def tearDown(self):
+        self.server.stop()
+
+    def test_proxy_with_bad_password_raises_httperror(self):
+        self._digest_auth_handler.add_password(self.REALM, self.URL,
+                                               self.USER, self.PASSWD+"bad")
+        FakeProxyHandler.digest_auth_handler.set_qop("auth")
+        self.assertRaises(urllib2.HTTPError,
+                          self.opener.open,
+                          self.URL)
+
+    def test_proxy_with_no_password_raises_httperror(self):
+        FakeProxyHandler.digest_auth_handler.set_qop("auth")
+        self.assertRaises(urllib2.HTTPError,
+                          self.opener.open,
+                          self.URL)
+
+    def test_proxy_qop_auth_works(self):
+        self._digest_auth_handler.add_password(self.REALM, self.URL,
+                                               self.USER, self.PASSWD)
+        FakeProxyHandler.digest_auth_handler.set_qop("auth")
+        result = self.opener.open(self.URL)
+        while result.read():
+            pass
+        result.close()
+
+    def test_proxy_qop_auth_int_works_or_throws_urlerror(self):
+        self._digest_auth_handler.add_password(self.REALM, self.URL,
+                                               self.USER, self.PASSWD)
+        FakeProxyHandler.digest_auth_handler.set_qop("auth-int")
+        try:
+            result = self.opener.open(self.URL)
+        except urllib2.URLError:
+            # It's okay if we don't support auth-int, but we certainly
+            # shouldn't receive any kind of exception here other than
+            # a URLError.
+            result = None
+        if result:
+            while result.read():
+                pass
+            result.close()
+
+def test_main():
+    # We will NOT depend on the network resource flag
+    # (Lib/test/regrtest.py -u network) since all tests here are only
+    # localhost.  However, if this is a bad rationale, then uncomment
+    # the next line.
+    #test_support.requires("network")
+
+    test_support.run_unittest(ProxyAuthTests)
+
+if __name__ == "__main__":
+    test_main()

Added: python/branches/cpy_merge/Tools/buildbot/build-amd64.bat
==============================================================================
--- (empty file)
+++ python/branches/cpy_merge/Tools/buildbot/build-amd64.bat	Thu Jun 14 23:10:12 2007
@@ -0,0 +1,6 @@
+ at rem Used by the buildbot "compile" step.
+setlocal
+cmd /c Tools\buildbot\external-amd64.bat
+call "%VS71COMNTOOLS%vsvars32.bat"
+REM cmd /q/c Tools\buildbot\kill_python.bat
+devenv.com /build ReleaseAMD64 PCbuild\pcbuild.sln

Added: python/branches/cpy_merge/Tools/buildbot/clean-amd64.bat
==============================================================================
--- (empty file)
+++ python/branches/cpy_merge/Tools/buildbot/clean-amd64.bat	Thu Jun 14 23:10:12 2007
@@ -0,0 +1,6 @@
+ at rem Used by the buildbot "clean" step.
+call "%VS71COMNTOOLS%vsvars32.bat"
+cd PCbuild
+ at echo Deleting .pyc/.pyo files ...
+python.exe rmpyc.py
+devenv.com /clean ReleaseAMD64 pcbuild.sln

Added: python/branches/cpy_merge/Tools/buildbot/external-amd64.bat
==============================================================================
--- (empty file)
+++ python/branches/cpy_merge/Tools/buildbot/external-amd64.bat	Thu Jun 14 23:10:12 2007
@@ -0,0 +1,44 @@
+ at rem Fetches (and builds if necessary) external dependencies
+setlocal
+
+ at rem need this so that 'devenv' is found
+call "%VS71COMNTOOLS%vsvars32.bat"
+ at rem set the build environment
+call "%MSSdk%\SetEnv" /XP64 /RETAIL
+
+ at rem Assume we start inside the Python source directory
+cd ..
+
+ at rem sqlite
+if not exist sqlite-source-3.3.4 (
+   svn export http://svn.python.org/projects/external/sqlite-source-3.3.4
+   if exist build\PCbuild\sqlite3.dll del build\PCbuild\sqlite3.dll
+)
+if not exist build\PCbuild\sqlite3.dll (
+   cd sqlite-source-3.3.4\amd64
+   cl ..\*.c
+   link /def:..\sqlite3.def  /dll *.obj /out:sqlite3.dll bufferoverflowU.lib
+   cd ..\..
+   copy sqlite-source-3.3.4\amd64\sqlite3.dll build\PCbuild
+)
+
+ at rem bzip
+if not exist bzip2-1.0.3 svn export http://svn.python.org/projects/external/bzip2-1.0.3
+
+ at rem Sleepycat db
+if not exist db-4.4.20 svn export http://svn.python.org/projects/external/db-4.4.20
+if not exist "db-4.4.20\build_win32\Release_AMD64\libdb44s.lib" (
+   cd db-4.4.20\build_win32
+   devenv Berkeley_DB.sln /build "Release AMD64" /project db_static /useenv
+   cd ..\..
+)
+
+ at rem OpenSSL
+if not exist openssl-0.9.8a svn export http://svn.python.org/projects/external/openssl-0.9.8a
+
+ at rem tcltk
+if not exist tcl8.4.12 (
+   if exist tcltk rd /s/q tcltk
+   svn export http://svn.python.org/projects/external/tcl8.4.12
+   svn export http://svn.python.org/projects/external/tk8.4.12
+)

Added: python/branches/cpy_merge/Tools/buildbot/test-amd64.bat
==============================================================================
--- (empty file)
+++ python/branches/cpy_merge/Tools/buildbot/test-amd64.bat	Thu Jun 14 23:10:12 2007
@@ -0,0 +1,3 @@
+ at rem Used by the buildbot "test" step.
+cd PCbuild
+call rt.bat -q -uall -rw


More information about the Python-checkins mailing list