Michael Merickel
2017-07-08 7dd9763452bfada736b96f88494caa73035d18c2
fix circular import in pyramid.viewderivers

this is a simple fix for 1.9-branch - a more comprehensive fix will be
done on master

fixes #3112
5 files modified
519 ■■■■ changed files
pyramid/config/util.py 64 ●●●● patch | view | raw | blame | history
pyramid/tests/test_config/test_util.py 194 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_util.py 194 ●●●●● patch | view | raw | blame | history
pyramid/util.py 52 ●●●●● patch | view | raw | blame | history
pyramid/viewderivers.py 15 ●●●● patch | view | raw | blame | history
pyramid/config/util.py
@@ -1,13 +1,10 @@
from hashlib import md5
import inspect
from pyramid.compat import (
    bytes_,
    getargspec,
    is_nonstr_iter
    )
from pyramid.compat import im_func
from pyramid.exceptions import ConfigurationError
from pyramid.registry import predvalseq
@@ -15,13 +12,21 @@
    TopologicalSorter,
    action_method,
    ActionInfo,
    takes_one_arg,
    )
from pyramid.viewderivers import (
    MAX_ORDER,
    DEFAULT_PHASH,
)
action_method = action_method # support bw compat imports
ActionInfo = ActionInfo # support bw compat imports
MAX_ORDER = 1 << 30
DEFAULT_PHASH = md5().hexdigest()
MAX_ORDER = MAX_ORDER  # support bw compat imports
DEFAULT_PHASH = DEFAULT_PHASH  # support bw compat imports
takes_one_arg = takes_one_arg  # support bw compat imports
class not_(object):
    """
@@ -189,52 +194,3 @@
            score = score | bit
        order = (MAX_ORDER - score) / (len(preds) + 1)
        return order, preds, phash.hexdigest()
def takes_one_arg(callee, attr=None, argname=None):
    ismethod = False
    if attr is None:
        attr = '__call__'
    if inspect.isroutine(callee):
        fn = callee
    elif inspect.isclass(callee):
        try:
            fn = callee.__init__
        except AttributeError:
            return False
        ismethod = hasattr(fn, '__call__')
    else:
        try:
            fn = getattr(callee, attr)
        except AttributeError:
            return False
    try:
        argspec = getargspec(fn)
    except TypeError:
        return False
    args = argspec[0]
    if hasattr(fn, im_func) or ismethod:
        # it's an instance method (or unbound method on py2)
        if not args:
            return False
        args = args[1:]
    if not args:
        return False
    if len(args) == 1:
        return True
    if argname:
        defaults = argspec[3]
        if defaults is None:
            defaults = ()
        if args[0] == argname:
            if len(args) - len(defaults) == 1:
                return True
    return False
pyramid/tests/test_config/test_util.py
@@ -391,200 +391,6 @@
        self.assertEqual(predicates[1](None, request), True)
        self.assertEqual(predicates[2](None, request), True)
class Test_takes_one_arg(unittest.TestCase):
    def _callFUT(self, view, attr=None, argname=None):
        from pyramid.config.util import takes_one_arg
        return takes_one_arg(view, attr=attr, argname=argname)
    def test_requestonly_newstyle_class_no_init(self):
        class foo(object):
            """ """
        self.assertFalse(self._callFUT(foo))
    def test_requestonly_newstyle_class_init_toomanyargs(self):
        class foo(object):
            def __init__(self, context, request):
                """ """
        self.assertFalse(self._callFUT(foo))
    def test_requestonly_newstyle_class_init_onearg_named_request(self):
        class foo(object):
            def __init__(self, request):
                """ """
        self.assertTrue(self._callFUT(foo))
    def test_newstyle_class_init_onearg_named_somethingelse(self):
        class foo(object):
            def __init__(self, req):
                """ """
        self.assertTrue(self._callFUT(foo))
    def test_newstyle_class_init_defaultargs_firstname_not_request(self):
        class foo(object):
            def __init__(self, context, request=None):
                """ """
        self.assertFalse(self._callFUT(foo))
    def test_newstyle_class_init_defaultargs_firstname_request(self):
        class foo(object):
            def __init__(self, request, foo=1, bar=2):
                """ """
        self.assertTrue(self._callFUT(foo, argname='request'))
    def test_newstyle_class_init_firstname_request_with_secondname(self):
        class foo(object):
            def __init__(self, request, two):
                """ """
        self.assertFalse(self._callFUT(foo))
    def test_newstyle_class_init_noargs(self):
        class foo(object):
            def __init__():
                """ """
        self.assertFalse(self._callFUT(foo))
    def test_oldstyle_class_no_init(self):
        class foo:
            """ """
        self.assertFalse(self._callFUT(foo))
    def test_oldstyle_class_init_toomanyargs(self):
        class foo:
            def __init__(self, context, request):
                """ """
        self.assertFalse(self._callFUT(foo))
    def test_oldstyle_class_init_onearg_named_request(self):
        class foo:
            def __init__(self, request):
                """ """
        self.assertTrue(self._callFUT(foo))
    def test_oldstyle_class_init_onearg_named_somethingelse(self):
        class foo:
            def __init__(self, req):
                """ """
        self.assertTrue(self._callFUT(foo))
    def test_oldstyle_class_init_defaultargs_firstname_not_request(self):
        class foo:
            def __init__(self, context, request=None):
                """ """
        self.assertFalse(self._callFUT(foo))
    def test_oldstyle_class_init_defaultargs_firstname_request(self):
        class foo:
            def __init__(self, request, foo=1, bar=2):
                """ """
        self.assertTrue(self._callFUT(foo, argname='request'), True)
    def test_oldstyle_class_init_noargs(self):
        class foo:
            def __init__():
                """ """
        self.assertFalse(self._callFUT(foo))
    def test_function_toomanyargs(self):
        def foo(context, request):
            """ """
        self.assertFalse(self._callFUT(foo))
    def test_function_with_attr_false(self):
        def bar(context, request):
            """ """
        def foo(context, request):
            """ """
        foo.bar = bar
        self.assertFalse(self._callFUT(foo, 'bar'))
    def test_function_with_attr_true(self):
        def bar(context, request):
            """ """
        def foo(request):
            """ """
        foo.bar = bar
        self.assertTrue(self._callFUT(foo, 'bar'))
    def test_function_onearg_named_request(self):
        def foo(request):
            """ """
        self.assertTrue(self._callFUT(foo))
    def test_function_onearg_named_somethingelse(self):
        def foo(req):
            """ """
        self.assertTrue(self._callFUT(foo))
    def test_function_defaultargs_firstname_not_request(self):
        def foo(context, request=None):
            """ """
        self.assertFalse(self._callFUT(foo))
    def test_function_defaultargs_firstname_request(self):
        def foo(request, foo=1, bar=2):
            """ """
        self.assertTrue(self._callFUT(foo, argname='request'))
    def test_function_noargs(self):
        def foo():
            """ """
        self.assertFalse(self._callFUT(foo))
    def test_instance_toomanyargs(self):
        class Foo:
            def __call__(self, context, request):
                """ """
        foo = Foo()
        self.assertFalse(self._callFUT(foo))
    def test_instance_defaultargs_onearg_named_request(self):
        class Foo:
            def __call__(self, request):
                """ """
        foo = Foo()
        self.assertTrue(self._callFUT(foo))
    def test_instance_defaultargs_onearg_named_somethingelse(self):
        class Foo:
            def __call__(self, req):
                """ """
        foo = Foo()
        self.assertTrue(self._callFUT(foo))
    def test_instance_defaultargs_firstname_not_request(self):
        class Foo:
            def __call__(self, context, request=None):
                """ """
        foo = Foo()
        self.assertFalse(self._callFUT(foo))
    def test_instance_defaultargs_firstname_request(self):
        class Foo:
            def __call__(self, request, foo=1, bar=2):
                """ """
        foo = Foo()
        self.assertTrue(self._callFUT(foo, argname='request'), True)
    def test_instance_nocall(self):
        class Foo: pass
        foo = Foo()
        self.assertFalse(self._callFUT(foo))
    def test_method_onearg_named_request(self):
        class Foo:
            def method(self, request):
                """ """
        foo = Foo()
        self.assertTrue(self._callFUT(foo.method))
    def test_function_annotations(self):
        def foo(bar):
            """ """
        # avoid SyntaxErrors in python2, this if effectively nop
        getattr(foo, '__annotations__', {}).update({'bar': 'baz'})
        self.assertTrue(self._callFUT(foo))
class TestNotted(unittest.TestCase):
    def _makeOne(self, predicate):
        from pyramid.config.util import Notted
pyramid/tests/test_util.py
@@ -855,6 +855,200 @@
        self.assertTrue('foo' not in obj.__dict__)
class Test_takes_one_arg(unittest.TestCase):
    def _callFUT(self, view, attr=None, argname=None):
        from pyramid.config.util import takes_one_arg
        return takes_one_arg(view, attr=attr, argname=argname)
    def test_requestonly_newstyle_class_no_init(self):
        class foo(object):
            """ """
        self.assertFalse(self._callFUT(foo))
    def test_requestonly_newstyle_class_init_toomanyargs(self):
        class foo(object):
            def __init__(self, context, request):
                """ """
        self.assertFalse(self._callFUT(foo))
    def test_requestonly_newstyle_class_init_onearg_named_request(self):
        class foo(object):
            def __init__(self, request):
                """ """
        self.assertTrue(self._callFUT(foo))
    def test_newstyle_class_init_onearg_named_somethingelse(self):
        class foo(object):
            def __init__(self, req):
                """ """
        self.assertTrue(self._callFUT(foo))
    def test_newstyle_class_init_defaultargs_firstname_not_request(self):
        class foo(object):
            def __init__(self, context, request=None):
                """ """
        self.assertFalse(self._callFUT(foo))
    def test_newstyle_class_init_defaultargs_firstname_request(self):
        class foo(object):
            def __init__(self, request, foo=1, bar=2):
                """ """
        self.assertTrue(self._callFUT(foo, argname='request'))
    def test_newstyle_class_init_firstname_request_with_secondname(self):
        class foo(object):
            def __init__(self, request, two):
                """ """
        self.assertFalse(self._callFUT(foo))
    def test_newstyle_class_init_noargs(self):
        class foo(object):
            def __init__():
                """ """
        self.assertFalse(self._callFUT(foo))
    def test_oldstyle_class_no_init(self):
        class foo:
            """ """
        self.assertFalse(self._callFUT(foo))
    def test_oldstyle_class_init_toomanyargs(self):
        class foo:
            def __init__(self, context, request):
                """ """
        self.assertFalse(self._callFUT(foo))
    def test_oldstyle_class_init_onearg_named_request(self):
        class foo:
            def __init__(self, request):
                """ """
        self.assertTrue(self._callFUT(foo))
    def test_oldstyle_class_init_onearg_named_somethingelse(self):
        class foo:
            def __init__(self, req):
                """ """
        self.assertTrue(self._callFUT(foo))
    def test_oldstyle_class_init_defaultargs_firstname_not_request(self):
        class foo:
            def __init__(self, context, request=None):
                """ """
        self.assertFalse(self._callFUT(foo))
    def test_oldstyle_class_init_defaultargs_firstname_request(self):
        class foo:
            def __init__(self, request, foo=1, bar=2):
                """ """
        self.assertTrue(self._callFUT(foo, argname='request'), True)
    def test_oldstyle_class_init_noargs(self):
        class foo:
            def __init__():
                """ """
        self.assertFalse(self._callFUT(foo))
    def test_function_toomanyargs(self):
        def foo(context, request):
            """ """
        self.assertFalse(self._callFUT(foo))
    def test_function_with_attr_false(self):
        def bar(context, request):
            """ """
        def foo(context, request):
            """ """
        foo.bar = bar
        self.assertFalse(self._callFUT(foo, 'bar'))
    def test_function_with_attr_true(self):
        def bar(context, request):
            """ """
        def foo(request):
            """ """
        foo.bar = bar
        self.assertTrue(self._callFUT(foo, 'bar'))
    def test_function_onearg_named_request(self):
        def foo(request):
            """ """
        self.assertTrue(self._callFUT(foo))
    def test_function_onearg_named_somethingelse(self):
        def foo(req):
            """ """
        self.assertTrue(self._callFUT(foo))
    def test_function_defaultargs_firstname_not_request(self):
        def foo(context, request=None):
            """ """
        self.assertFalse(self._callFUT(foo))
    def test_function_defaultargs_firstname_request(self):
        def foo(request, foo=1, bar=2):
            """ """
        self.assertTrue(self._callFUT(foo, argname='request'))
    def test_function_noargs(self):
        def foo():
            """ """
        self.assertFalse(self._callFUT(foo))
    def test_instance_toomanyargs(self):
        class Foo:
            def __call__(self, context, request):
                """ """
        foo = Foo()
        self.assertFalse(self._callFUT(foo))
    def test_instance_defaultargs_onearg_named_request(self):
        class Foo:
            def __call__(self, request):
                """ """
        foo = Foo()
        self.assertTrue(self._callFUT(foo))
    def test_instance_defaultargs_onearg_named_somethingelse(self):
        class Foo:
            def __call__(self, req):
                """ """
        foo = Foo()
        self.assertTrue(self._callFUT(foo))
    def test_instance_defaultargs_firstname_not_request(self):
        class Foo:
            def __call__(self, context, request=None):
                """ """
        foo = Foo()
        self.assertFalse(self._callFUT(foo))
    def test_instance_defaultargs_firstname_request(self):
        class Foo:
            def __call__(self, request, foo=1, bar=2):
                """ """
        foo = Foo()
        self.assertTrue(self._callFUT(foo, argname='request'), True)
    def test_instance_nocall(self):
        class Foo: pass
        foo = Foo()
        self.assertFalse(self._callFUT(foo))
    def test_method_onearg_named_request(self):
        class Foo:
            def method(self, request):
                """ """
        foo = Foo()
        self.assertTrue(self._callFUT(foo.method))
    def test_function_annotations(self):
        def foo(bar):
            """ """
        # avoid SyntaxErrors in python2, this if effectively nop
        getattr(foo, '__annotations__', {}).update({'bar': 'baz'})
        self.assertTrue(self._callFUT(foo))
def dummyfunc(): pass
pyramid/util.py
@@ -17,6 +17,8 @@
    )
from pyramid.compat import (
    getargspec,
    im_func,
    is_nonstr_iter,
    integer_types,
    string_types,
@@ -645,3 +647,53 @@
    return (pattern[0] == "." and
            (host.endswith(pattern) or host == pattern[1:]) or
            pattern == host)
def takes_one_arg(callee, attr=None, argname=None):
    ismethod = False
    if attr is None:
        attr = '__call__'
    if inspect.isroutine(callee):
        fn = callee
    elif inspect.isclass(callee):
        try:
            fn = callee.__init__
        except AttributeError:
            return False
        ismethod = hasattr(fn, '__call__')
    else:
        try:
            fn = getattr(callee, attr)
        except AttributeError:
            return False
    try:
        argspec = getargspec(fn)
    except TypeError:
        return False
    args = argspec[0]
    if hasattr(fn, im_func) or ismethod:
        # it's an instance method (or unbound method on py2)
        if not args:
            return False
        args = args[1:]
    if not args:
        return False
    if len(args) == 1:
        return True
    if argname:
        defaults = argspec[3]
        if defaults is None:
            defaults = ()
        if args[0] == argname:
            if len(args) - len(defaults) == 1:
                return True
    return False
pyramid/viewderivers.py
@@ -1,3 +1,4 @@
from hashlib import md5
import inspect
from zope.interface import (
@@ -28,22 +29,22 @@
    is_unbound_method,
    )
from pyramid.config.util import (
    DEFAULT_PHASH,
    MAX_ORDER,
    takes_one_arg,
    )
from pyramid.exceptions import (
    ConfigurationError,
    PredicateMismatch,
    )
from pyramid.httpexceptions import HTTPForbidden
from pyramid.util import object_description
from pyramid.util import (
    object_description,
    takes_one_arg,
    )
from pyramid.view import render_view_to_response
from pyramid import renderers
MAX_ORDER = 1 << 30
DEFAULT_PHASH = md5().hexdigest()
def view_description(view):
    try:
        return view.__text__