summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Merickel <michael@merickel.org>2018-11-14 18:45:53 -0600
committerMichael Merickel <michael@merickel.org>2018-11-14 18:59:43 -0600
commit9ead1d8e84edcb86ea9e07b4d2c31e7b74a098ed (patch)
tree08c0f0389e2e467f8b104a98cc3e6bd19ffc8ab1
parent656ce2b499bd05ceb9b0ae492a0be15a07dc283f (diff)
downloadpyramid-9ead1d8e84edcb86ea9e07b4d2c31e7b74a098ed.tar.gz
pyramid-9ead1d8e84edcb86ea9e07b4d2c31e7b74a098ed.tar.bz2
pyramid-9ead1d8e84edcb86ea9e07b4d2c31e7b74a098ed.zip
move is_unbound_method to pyramid.util
-rw-r--r--src/pyramid/compat.py28
-rw-r--r--src/pyramid/util.py34
-rw-r--r--src/pyramid/viewderivers.py9
-rw-r--r--tests/test_compat.py32
-rw-r--r--tests/test_config/test_init.py6
-rw-r--r--tests/test_config/test_views.py14
-rw-r--r--tests/test_util.py23
7 files changed, 62 insertions, 84 deletions
diff --git a/src/pyramid/compat.py b/src/pyramid/compat.py
index 3ad8720d6..12b4b7b00 100644
--- a/src/pyramid/compat.py
+++ b/src/pyramid/compat.py
@@ -76,9 +76,6 @@ def is_nonstr_iter(v):
return hasattr(v, '__iter__')
-im_func = '__func__'
-im_self = '__self__'
-
from http.cookies import SimpleCookie
from html import escape
@@ -95,28 +92,3 @@ from urllib.parse import unquote_to_bytes
def unquote_bytes_to_wsgi(bytestring):
return unquote_to_bytes(bytestring).decode('latin-1')
-
-
-def is_bound_method(ob):
- return inspect.ismethod(ob) and getattr(ob, im_self, None) is not None
-
-
-# support annotations and keyword-only arguments in PY3
-from inspect import getfullargspec as getargspec
-
-
-def is_unbound_method(fn):
- """
- This consistently verifies that the callable is bound to a
- class.
- """
- is_bound = is_bound_method(fn)
-
- if not is_bound and inspect.isroutine(fn):
- spec = getargspec(fn)
- has_self = len(spec.args) > 0 and spec.args[0] == 'self'
-
- if inspect.isfunction(fn) and has_self:
- return True
-
- return False
diff --git a/src/pyramid/util.py b/src/pyramid/util.py
index d3e5d1578..23cce195a 100644
--- a/src/pyramid/util.py
+++ b/src/pyramid/util.py
@@ -6,14 +6,7 @@ import weakref
from pyramid.exceptions import ConfigurationError, CyclicDependencyError
-from pyramid.compat import (
- getargspec,
- im_func,
- is_nonstr_iter,
- bytes_,
- text_,
- native_,
-)
+from pyramid.compat import is_nonstr_iter, bytes_, text_, native_
from pyramid.path import DottedNameResolver as _DottedNameResolver
@@ -616,13 +609,13 @@ def takes_one_arg(callee, attr=None, argname=None):
return False
try:
- argspec = getargspec(fn)
+ argspec = inspect.getfullargspec(fn)
except TypeError:
return False
args = argspec[0]
- if hasattr(fn, im_func) or ismethod:
+ if hasattr(fn, '__func__') or ismethod:
# it's an instance method (or unbound method on py2)
if not args:
return False
@@ -653,3 +646,24 @@ class SimpleSerializer(object):
def dumps(self, appstruct):
return bytes_(appstruct)
+
+
+def is_bound_method(ob):
+ return inspect.ismethod(ob) and getattr(ob, '__self__', None) is not None
+
+
+def is_unbound_method(fn):
+ """
+ This consistently verifies that the callable is bound to a
+ class.
+ """
+ is_bound = is_bound_method(fn)
+
+ if not is_bound and inspect.isroutine(fn):
+ spec = inspect.getfullargspec(fn)
+ has_self = len(spec.args) > 0 and spec.args[0] == 'self'
+
+ if inspect.isfunction(fn) and has_self:
+ return True
+
+ return False
diff --git a/src/pyramid/viewderivers.py b/src/pyramid/viewderivers.py
index fbe0c252c..181cc9e5c 100644
--- a/src/pyramid/viewderivers.py
+++ b/src/pyramid/viewderivers.py
@@ -17,11 +17,14 @@ from pyramid.interfaces import (
IViewMapperFactory,
)
-from pyramid.compat import is_bound_method, is_unbound_method
-
from pyramid.exceptions import ConfigurationError
from pyramid.httpexceptions import HTTPForbidden
-from pyramid.util import object_description, takes_one_arg
+from pyramid.util import (
+ object_description,
+ takes_one_arg,
+ is_bound_method,
+ is_unbound_method,
+)
from pyramid.view import render_view_to_response
from pyramid import renderers
diff --git a/tests/test_compat.py b/tests/test_compat.py
deleted file mode 100644
index 4a14caedf..000000000
--- a/tests/test_compat.py
+++ /dev/null
@@ -1,32 +0,0 @@
-import unittest
-from pyramid.compat import is_unbound_method
-
-
-class TestUnboundMethods(unittest.TestCase):
- def test_old_style_bound(self):
- self.assertFalse(is_unbound_method(OldStyle().run))
-
- def test_new_style_bound(self):
- self.assertFalse(is_unbound_method(NewStyle().run))
-
- def test_old_style_unbound(self):
- self.assertTrue(is_unbound_method(OldStyle.run))
-
- def test_new_style_unbound(self):
- self.assertTrue(is_unbound_method(NewStyle.run))
-
- def test_normal_func_unbound(self):
- def func(): # pragma: no cover
- return 'OK'
-
- self.assertFalse(is_unbound_method(func))
-
-
-class OldStyle:
- def run(self): # pragma: no cover
- return 'OK'
-
-
-class NewStyle(object):
- def run(self): # pragma: no cover
- return 'OK'
diff --git a/tests/test_config/test_init.py b/tests/test_config/test_init.py
index 1cd63f113..ce2b042ec 100644
--- a/tests/test_config/test_init.py
+++ b/tests/test_config/test_init.py
@@ -1,8 +1,6 @@
import os
import unittest
-from pyramid.compat import im_func
-
from . import dummy_tween_factory
from . import dummy_include
from . import dummy_extend
@@ -1205,7 +1203,7 @@ test_config.dummy_include2"""
directives = {'foo': (foo, True)}
config.registry._directives = directives
foo_meth = config.foo
- self.assertTrue(getattr(foo_meth, im_func).__docobj__ is foo)
+ self.assertTrue(getattr(foo_meth, '__func__').__docobj__ is foo)
def test___getattr__matches_no_action_wrap(self):
config = self._makeOne()
@@ -1216,7 +1214,7 @@ test_config.dummy_include2"""
directives = {'foo': (foo, False)}
config.registry._directives = directives
foo_meth = config.foo
- self.assertTrue(getattr(foo_meth, im_func) is foo)
+ self.assertTrue(getattr(foo_meth, '__func__') is foo)
class TestConfigurator_add_directive(unittest.TestCase):
diff --git a/tests/test_config/test_views.py b/tests/test_config/test_views.py
index aa5b67050..d530542b7 100644
--- a/tests/test_config/test_views.py
+++ b/tests/test_config/test_views.py
@@ -3,7 +3,7 @@ import unittest
from zope.interface import implementer
from pyramid import testing
-from pyramid.compat import im_func, text_
+from pyramid.compat import text_
from pyramid.exceptions import ConfigurationError
from pyramid.exceptions import ConfigurationExecutionError
from pyramid.exceptions import ConfigurationConflictError
@@ -3723,16 +3723,16 @@ class Test_preserve_view_attrs(unittest.TestCase):
self.assertTrue(view1.__module__ is view2.__module__)
self.assertTrue(view1.__name__ is view2.__name__)
self.assertTrue(
- getattr(view1.__call_permissive__, im_func)
- is getattr(view2.__call_permissive__, im_func)
+ getattr(view1.__call_permissive__, '__func__')
+ is getattr(view2.__call_permissive__, '__func__')
)
self.assertTrue(
- getattr(view1.__permitted__, im_func)
- is getattr(view2.__permitted__, im_func)
+ getattr(view1.__permitted__, '__func__')
+ is getattr(view2.__permitted__, '__func__')
)
self.assertTrue(
- getattr(view1.__predicated__, im_func)
- is getattr(view2.__predicated__, im_func)
+ getattr(view1.__predicated__, '__func__')
+ is getattr(view2.__predicated__, '__func__')
)
diff --git a/tests/test_util.py b/tests/test_util.py
index 8af5fe557..676290676 100644
--- a/tests/test_util.py
+++ b/tests/test_util.py
@@ -1223,3 +1223,26 @@ class TestSimpleSerializer(unittest.TestCase):
def test_dumps(self):
inst = self._makeOne()
self.assertEqual(inst.dumps('abc'), bytes_('abc'))
+
+
+class TestUnboundMethods(unittest.TestCase):
+ class Dummy(object):
+ def run(self): # pragma: no cover
+ return 'OK'
+
+ def _callFUT(self, val):
+ from pyramid.util import is_unbound_method
+
+ return is_unbound_method(val)
+
+ def test_bound_method(self):
+ self.assertFalse(self._callFUT(self.Dummy().run))
+
+ def test_unbound_method(self):
+ self.assertTrue(self._callFUT(self.Dummy.run))
+
+ def test_normal_func_unbound(self):
+ def func(): # pragma: no cover
+ return 'OK'
+
+ self.assertFalse(self._callFUT(func))