Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r49647:ddbc82ef4d8f
Date: 2011-11-21 20:30 +0100
http://bitbucket.org/pypy/pypy/changeset/ddbc82ef4d8f/

Log:    Test and fix: instead of using a custom __setattr__ handler (and no
        __getattr__, creating confusion), create a bunch of properties.

diff --git a/pypy/module/pyexpat/interp_pyexpat.py 
b/pypy/module/pyexpat/interp_pyexpat.py
--- a/pypy/module/pyexpat/interp_pyexpat.py
+++ b/pypy/module/pyexpat/interp_pyexpat.py
@@ -3,9 +3,7 @@
 from pypy.interpreter.gateway import NoneNotWrapped
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.error import OperationError
-from pypy.objspace.descroperation import object_setattr
 from pypy.rlib import rgc
-from pypy.rlib.unroll import unrolling_iterable
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.rpython.tool import rffi_platform
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
@@ -339,8 +337,6 @@
     'XML_SetUnknownEncodingHandler',
     [XML_Parser, callback_type, rffi.VOIDP], lltype.Void)
 
-ENUMERATE_SETTERS = unrolling_iterable(SETTERS.items())
-
 # Declarations of external functions
 
 XML_ParserCreate = expat_external(
@@ -545,15 +541,19 @@
                 self.buffer_used = 0
         return False
 
+    def gethandler(self, space, name, index):
+        if name == 'CharacterDataHandler':
+            return self.w_character_data_handler or space.w_None
+        return self.handlers[index]
+
     def sethandler(self, space, name, w_handler, index, setter, handler):
-
         if name == 'CharacterDataHandler':
             self.flush_character_buffer(space)
             if space.is_w(w_handler, space.w_None):
                 self.w_character_data_handler = None
             else:
                 self.w_character_data_handler = w_handler
-
+        #
         self.handlers[index] = w_handler
         setter(self.itself, handler)
 
@@ -580,21 +580,29 @@
         return True
 
 
-    @unwrap_spec(name=str)
-    def setattr(self, space, name, w_value):
-        if name == "namespace_prefixes":
-            XML_SetReturnNSTriplet(self.itself, space.int_w(w_value))
-            return
+    @staticmethod
+    def _make_property(name):
+        index, setter, handler = SETTERS[name]
+        #
+        def descr_get_property(self, space):
+            return self.gethandler(space, name, index)
+        #
+        def descr_set_property(self, space, w_value):
+            return self.sethandler(space, name, w_value,
+                                   index, setter, handler)
+        #
+        return GetSetProperty(descr_get_property,
+                              descr_set_property,
+                              cls=W_XMLParserType)
 
-        for handler_name, (index, setter, handler) in ENUMERATE_SETTERS:
-            if name == handler_name:
-                return self.sethandler(space, handler_name, w_value,
-                                       index, setter, handler)
 
-        # fallback to object.__setattr__()
-        return space.call_function(
-            object_setattr(space),
-            space.wrap(self), space.wrap(name), w_value)
+    def get_namespace_prefixes(self, space):
+        raise OperationError(space.w_AttributeError,
+            space.wrap("not implemented: reading namespace_prefixes"))
+
+    @unwrap_spec(value=int)
+    def set_namespace_prefixes(self, space, value):
+        XML_SetReturnNSTriplet(self.itself, bool(value))
 
     # Parse methods
 
@@ -732,10 +740,18 @@
 if XML_COMBINED_VERSION >= 19505:
     XMLParser_methods.append('UseForeignDTD')
 
+_XMLParser_extras = {}
+for name in XMLParser_methods:
+    _XMLParser_extras[name] = interp2app(getattr(W_XMLParserType, name))
+for name in SETTERS:
+    _XMLParser_extras[name] = W_XMLParserType._make_property(name)
+
 W_XMLParserType.typedef = TypeDef(
     "pyexpat.XMLParserType",
     __doc__ = "XML parser",
-    __setattr__ = interp2app(W_XMLParserType.setattr),
+    namespace_prefixes = GetSetProperty(W_XMLParserType.get_namespace_prefixes,
+                                        W_XMLParserType.set_namespace_prefixes,
+                                        cls=W_XMLParserType),
     returns_unicode = bool_property('returns_unicode', W_XMLParserType),
     ordered_attributes = bool_property('ordered_attributes', W_XMLParserType),
     specified_attributes = bool_property('specified_attributes', 
W_XMLParserType),
@@ -754,8 +770,7 @@
     CurrentColumnNumber = 
GetSetProperty(W_XMLParserType.descr_ErrorColumnNumber, cls=W_XMLParserType),
     CurrentByteIndex = GetSetProperty(W_XMLParserType.descr_ErrorByteIndex, 
cls=W_XMLParserType),
 
-    **dict((name, interp2app(getattr(W_XMLParserType, name)))
-           for name in XMLParser_methods)
+    **_XMLParser_extras
     )
 
 def ParserCreate(space, w_encoding=None, w_namespace_separator=None,
diff --git a/pypy/module/pyexpat/test/test_parser.py 
b/pypy/module/pyexpat/test/test_parser.py
--- a/pypy/module/pyexpat/test/test_parser.py
+++ b/pypy/module/pyexpat/test/test_parser.py
@@ -52,6 +52,19 @@
                 assert res == 1
                 assert data == [u"\u00f6"]
 
+    def test_get_handler(self):
+        import pyexpat
+        p = pyexpat.ParserCreate()
+        assert p.StartElementHandler is None
+        assert p.EndElementHandler is None
+        def f(*args): pass
+        p.StartElementHandler = f
+        assert p.StartElementHandler is f
+        def g(*args): pass
+        p.EndElementHandler = g
+        assert p.StartElementHandler is f
+        assert p.EndElementHandler is g
+
     def test_intern(self):
         import pyexpat
         p = pyexpat.ParserCreate()
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to