Skip to content

Commit

Permalink
Allow calling builtin_method objects by default (#112)
Browse files Browse the repository at this point in the history
The type of these objects is a subclass of `types.BuiltinMethodType`, but not
identical to it.  This caused downstream failures on Python >= 3.12 due to
refactoring of the `io` module, such as
zopefoundation/zope.file#13.
  • Loading branch information
cjwatson authored Aug 16, 2024
1 parent 7e03db2 commit 6ad2d1e
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 0 deletions.
6 changes: 6 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
7.1 (unreleased)
----------------

- Allow calling methods of type ``<class 'builtin_method'>`` by default. In
particular, Python 3.12 refactored the ``io`` module in such a way as to
slightly change the types of some methods, causing ``zope.security`` to no
longer consider them callable. See `zope.file issue #13
<https:/zopefoundation/zope.file/issues/13>`.


7.0 (2024-05-30)
----------------
Expand Down
9 changes: 9 additions & 0 deletions src/zope/security/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
import abc
import datetime
import decimal
import io
import os
import sys
import types
Expand Down Expand Up @@ -879,6 +880,14 @@ def f(): # pragma: no cover
types.MethodType: _callableChecker,
types.BuiltinFunctionType: _callableChecker,
types.BuiltinMethodType: _callableChecker,
# At least on Python 3.5-3.12, types.BuiltinFunctionType and
# types.BuiltinMethodType are both <class 'builtin_function_or_method'>,
# or PyCFunctionType. However, some builtin methods are <class
# 'builtin_method'> instead, or PyCMethodType, which is a subclass of
# PyCFunctionType but not identical to it. As of Python 3.12, the io
# module makes more use of PyCMethodType, so we can use it to identify
# that type.
type(io.BytesIO().getbuffer): _callableChecker,
# method-wrapper
type(().__repr__): _callableChecker,
type: _typeChecker,
Expand Down
7 changes: 7 additions & 0 deletions src/zope/security/tests/test_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
##############################################################################
"""Security proxy tests
"""
import io
import os
import unittest

from zope.security._compat import PURE_PYTHON
Expand Down Expand Up @@ -1815,6 +1817,11 @@ def test_method_wrapper(self):

self.assertEqual(ProxyFactory({}).__repr__(), '{}')

def test_builtin_method(self):
from zope.security.proxy import ProxyFactory

self.assertEqual(ProxyFactory(io.FileIO(os.devnull, 'rb').read)(), b'')


def test_using_mapping_slots_hack():
"""The security proxy will use mapping slots, on the checker to go faster
Expand Down

0 comments on commit 6ad2d1e

Please sign in to comment.