summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_descr.py
diff options
context:
space:
mode:
authorArmin Rigo <arigo@tunes.org>2007-05-02 19:23:31 (GMT)
committerArmin Rigo <arigo@tunes.org>2007-05-02 19:23:31 (GMT)
commit9790a2706573359e02fcfc5f18f9907467f4ec49 (patch)
treed953c06fbbb8325b8ed86e707ed17f0b43b870dd /Lib/test/test_descr.py
parentd83eb316dce49606041304afb6b68e85fb1794af (diff)
downloadcpython-9790a2706573359e02fcfc5f18f9907467f4ec49.zip
cpython-9790a2706573359e02fcfc5f18f9907467f4ec49.tar.gz
cpython-9790a2706573359e02fcfc5f18f9907467f4ec49.tar.bz2
Fix for #1303614 and #1174712:
- __dict__ descriptor abuse for subclasses of built-in types - subclassing from both ModuleType and another built-in types Thanks zseil for the patch.
Diffstat (limited to 'Lib/test/test_descr.py')
-rw-r--r--Lib/test/test_descr.py80
1 files changed, 78 insertions, 2 deletions
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
index 53181ac..57cef44 100644
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -3,6 +3,7 @@
from test.test_support import verify, vereq, verbose, TestFailed, TESTFN, get_original_stdout
from copy import deepcopy
import warnings
+import types
warnings.filterwarnings("ignore",
r'complex divmod\(\), // and % are deprecated$',
@@ -861,6 +862,16 @@ def pymods():
("getattr", "foo"),
("delattr", "foo")])
+ # http://python.org/sf/1174712
+ try:
+ class Module(types.ModuleType, str):
+ pass
+ except TypeError:
+ pass
+ else:
+ raise TestFailed("inheriting from ModuleType and str at the "
+ "same time should fail")
+
def multi():
if verbose: print "Testing multiple inheritance..."
class C(object):
@@ -2907,8 +2918,73 @@ def setdict():
cant(a, [])
cant(a, 1)
del a.__dict__ # Deleting __dict__ is allowed
- # Classes don't allow __dict__ assignment
- cant(C, {})
+
+ class Base(object):
+ pass
+ def verify_dict_readonly(x):
+ """
+ x has to be an instance of a class inheriting from Base.
+ """
+ cant(x, {})
+ try:
+ del x.__dict__
+ except (AttributeError, TypeError):
+ pass
+ else:
+ raise TestFailed, "shouldn't allow del %r.__dict__" % x
+ dict_descr = Base.__dict__["__dict__"]
+ try:
+ dict_descr.__set__(x, {})
+ except (AttributeError, TypeError):
+ pass
+ else:
+ raise TestFailed, "dict_descr allowed access to %r's dict" % x
+
+ # Classes don't allow __dict__ assignment and have readonly dicts
+ class Meta1(type, Base):
+ pass
+ class Meta2(Base, type):
+ pass
+ class D(object):
+ __metaclass__ = Meta1
+ class E(object):
+ __metaclass__ = Meta2
+ for cls in C, D, E:
+ verify_dict_readonly(cls)
+ class_dict = cls.__dict__
+ try:
+ class_dict["spam"] = "eggs"
+ except TypeError:
+ pass
+ else:
+ raise TestFailed, "%r's __dict__ can be modified" % cls
+
+ # Modules also disallow __dict__ assignment
+ class Module1(types.ModuleType, Base):
+ pass
+ class Module2(Base, types.ModuleType):
+ pass
+ for ModuleType in Module1, Module2:
+ mod = ModuleType("spam")
+ verify_dict_readonly(mod)
+ mod.__dict__["spam"] = "eggs"
+
+ # Exception's __dict__ can be replaced, but not deleted
+ class Exception1(Exception, Base):
+ pass
+ class Exception2(Base, Exception):
+ pass
+ for ExceptionType in Exception, Exception1, Exception2:
+ e = ExceptionType()
+ e.__dict__ = {"a": 1}
+ vereq(e.a, 1)
+ try:
+ del e.__dict__
+ except (TypeError, AttributeError):
+ pass
+ else:
+ raise TestFaied, "%r's __dict__ can be deleted" % e
+
def pickles():
if verbose: