Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python 3.10 failures #130

Closed
thomasgoirand opened this issue Nov 12, 2021 · 1 comment · Fixed by #131
Closed

Python 3.10 failures #130

thomasgoirand opened this issue Nov 12, 2021 · 1 comment · Fixed by #131

Comments

@thomasgoirand
Copy link

thomasgoirand commented Nov 12, 2021

Hi,

I maintain Pecan as a Debian package in Debian. As Python 3.10 is currently in Experimental, and is about to be uploaded to Unstable, I have tried running the unit tests (which are run at package build time), and there's 4 failures that I am pasting below. Please help me to fix them:

=================================== FAILURES ===================================
__________________ TestControllerArguments.test_no_remainder ___________________

self = <pecan.tests.test_base.TestControllerArguments testMethod=test_no_remainder>

    def test_no_remainder(self):
        try:
>           r = self.app_.get('/eater')

pecan/tests/test_base.py:992: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <webtest.app.TestApp object at 0x7f3bbc38a7d0>, url = '/eater'
params = None, headers = None, extra_environ = None, status = None
expect_errors = False, xhr = False

    def get(self, url, params=None, headers=None, extra_environ=None,
            status=None, expect_errors=False, xhr=False):
        """
        Do a GET request given the url path.
    
        :param params:
            A query string, or a dictionary that will be encoded
            into a query string.  You may also include a URL query
            string on the ``url``.
        :param headers:
            Extra headers to send.
        :type headers:
            dictionary
        :param extra_environ:
            Environmental variables that should be added to the request.
        :type extra_environ:
            dictionary
        :param status:
            The HTTP status code you expect in response (if not 200 or 3xx).
            You can also use a wildcard, like ``'3*'`` or ``'*'``.
        :type status:
            integer or string
        :param expect_errors:
            If this is False, then if anything is written to
            environ ``wsgi.errors`` it will be an error.
            If it is True, then non-200/3xx responses are also okay.
        :type expect_errors:
            boolean
        :param xhr:
            If this is true, then marks response as ajax. The same as
            headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }
        :type xhr:
            boolean
    
        :returns: :class:`webtest.TestResponse` instance.
    
        """
        environ = self._make_environ(extra_environ)
        url = str(url)
        url = self._remove_fragment(url)
        if params:
            url = utils.build_params(url, params)
        if str('?') in url:
            url, environ['QUERY_STRING'] = url.split(str('?'), 1)
        else:
            environ['QUERY_STRING'] = str('')
        req = self.RequestClass.blank(url, environ)
        if xhr:
            headers = self._add_xhr_header(headers)
        if headers:
            req.headers.update(headers)
>       return self.do_request(req, status=status,
                               expect_errors=expect_errors)

/usr/lib/python3/dist-packages/webtest/app.py:327: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <webtest.app.TestApp object at 0x7f3bbc38a7d0>
req = <TestRequest at 0x7f3bbc38a620 GET http://localhost/eater>, status = None
expect_errors = False

    def do_request(self, req, status=None, expect_errors=None):
        """
        Executes the given webob Request (``req``), with the expected
        ``status``.  Generally :meth:`~webtest.TestApp.get` and
        :meth:`~webtest.TestApp.post` are used instead.
    
        To use this::
    
            req = webtest.TestRequest.blank('url', ...args...)
            resp = app.do_request(req)
    
        .. note::
    
            You can pass any keyword arguments to
            ``TestRequest.blank()``, which will be set on the request.
            These can be arguments like ``content_type``, ``accept``, etc.
    
        """
    
        errors = StringIO()
        req.environ['wsgi.errors'] = errors
        script_name = req.environ.get('SCRIPT_NAME', '')
        if script_name and req.path_info.startswith(script_name):
            req.path_info = req.path_info[len(script_name):]
    
        # set framework hooks
        req.environ['paste.testing'] = True
        req.environ['paste.testing_variables'] = {}
    
        # set request cookies
        self.cookiejar.add_cookie_header(utils._RequestCookieAdapter(req))
    
        # verify wsgi compatibility
        app = lint.middleware(self.app) if self.lint else self.app
    
        # FIXME: should it be an option to not catch exc_info?
>       res = req.get_response(app, catch_exc_info=True)

/usr/lib/python3/dist-packages/webtest/app.py:623: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <TestRequest at 0x7f3bbc38a620 GET http://localhost/eater>
application = <function middleware.<locals>.lint_app at 0x7f3bbc44d510>
catch_exc_info = True

    def send(self, application=None, catch_exc_info=False):
        """
        Like ``.call_application(application)``, except returns a
        response object with ``.status``, ``.headers``, and ``.body``
        attributes.
    
        This will use ``self.ResponseClass`` to figure out the class
        of the response object to return.
    
        If ``application`` is not given, this will send the request to
        ``self.make_default_send_app()``
        """
        if application is None:
            application = self.make_default_send_app()
        if catch_exc_info:
>           status, headers, app_iter, exc_info = self.call_application(
                application, catch_exc_info=True)

/usr/lib/python3/dist-packages/webob/request.py:1309: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <TestRequest at 0x7f3bbc38a620 GET http://localhost/eater>
application = <function middleware.<locals>.lint_app at 0x7f3bbc44d510>
catch_exc_info = True

    def call_application(self, application, catch_exc_info=False):
        """
        Call the given WSGI application, returning ``(status_string,
        headerlist, app_iter)``
    
        Be sure to call ``app_iter.close()`` if it's there.
    
        If catch_exc_info is true, then returns ``(status_string,
        headerlist, app_iter, exc_info)``, where the fourth item may
        be None, but won't be if there was an exception.  If you don't
        do this and there was an exception, the exception will be
        raised directly.
        """
        if self.is_body_seekable:
            self.body_file_raw.seek(0)
        captured = []
        output = []
        def start_response(status, headers, exc_info=None):
            if exc_info is not None and not catch_exc_info:
                reraise(exc_info)
            captured[:] = [status, headers, exc_info]
            return output.append
>       app_iter = application(self.environ, start_response)

/usr/lib/python3/dist-packages/webob/request.py:1278: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = ({'HTTP_HOST': 'localhost:80', 'PATH_INFO': '/eater', 'QUERY_STRING': '', 'REQUEST_METHOD': 'GET', ...}, <function BaseRequest.call_application.<locals>.start_response at 0x7f3bbc40eb90>)
kw = {}
environ = {'HTTP_HOST': 'localhost:80', 'PATH_INFO': '/eater', 'QUERY_STRING': '', 'REQUEST_METHOD': 'GET', ...}
start_response_wrapper = <function middleware.<locals>.lint_app.<locals>.start_response_wrapper at 0x7f3bbc40ec20>

    def lint_app(*args, **kw):
        assert len(args) == 2, "Two arguments required"
        assert not kw, "No keyword arguments allowed"
        environ, start_response = args
    
        check_environ(environ)
    
        # We use this to check if the application returns without
        # calling start_response:
        start_response_started = []
    
        def start_response_wrapper(*args, **kw):
            assert len(args) == 2 or len(args) == 3, (
                "Invalid number of arguments: %s" % args)
            assert not kw, "No keyword arguments allowed"
            status = args[0]
            headers = args[1]
            if len(args) == 3:
                exc_info = args[2]
            else:
                exc_info = None
    
            check_status(status)
            check_headers(headers)
            check_content_type(status, headers)
            check_exc_info(exc_info)
    
            start_response_started.append(None)
            return WriteWrapper(start_response(*args))
    
        environ['wsgi.input'] = InputWrapper(environ['wsgi.input'])
        environ['wsgi.errors'] = ErrorWrapper(environ['wsgi.errors'])
    
>       iterator = application(environ, start_response_wrapper)

/usr/lib/python3/dist-packages/webtest/lint.py:201: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pecan.core.Pecan object at 0x7f3bbc414370>
environ = {'HTTP_HOST': 'localhost:80', 'PATH_INFO': '/eater', 'QUERY_STRING': '', 'REQUEST_METHOD': 'GET', ...}
start_response = <function middleware.<locals>.lint_app.<locals>.start_response_wrapper at 0x7f3bbc40ec20>

    def __call__(self, environ, start_response):
        try:
            state.hooks = []
            state.app = self
            state.controller = None
            state.arguments = None
>           return super(Pecan, self).__call__(environ, start_response)

pecan/core.py:840: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pecan.core.Pecan object at 0x7f3bbc414370>
environ = {'HTTP_HOST': 'localhost:80', 'PATH_INFO': '/eater', 'QUERY_STRING': '', 'REQUEST_METHOD': 'GET', ...}
start_response = <function middleware.<locals>.lint_app.<locals>.start_response_wrapper at 0x7f3bbc40ec20>

    def __call__(self, environ, start_response):
        '''
        Implements the WSGI specification for Pecan applications, utilizing
        ``WebOb``.
        '''
    
        # create the request and response object
        req = self.request_cls(environ)
        resp = self.response_cls()
        state = RoutingState(req, resp, self)
        environ['pecan.locals'] = {
            'request': req,
            'response': resp
        }
        controller = None
    
        # track internal redirects
        internal_redirect = False
    
        # handle the request
        try:
            # add context and environment to the request
            req.context = environ.get('pecan.recursive.context', {})
            req.pecan = dict(content_type=None)
    
            controller, args, kwargs = self.find_controller(state)
>           self.invoke_controller(controller, args, kwargs, state)

pecan/core.py:683: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pecan.core.Pecan object at 0x7f3bbc414370>
controller = <bound method TestControllerArguments.app_.<locals>.RootController.eater of <pecan.tests.test_base.TestControllerArguments.app_.<locals>.RootController object at 0x7f3bbc414760>>
args = [], kwargs = {}
state = <pecan.core.RoutingState object at 0x7f3bbc416d70>

    def invoke_controller(self, controller, args, kwargs, state):
        '''
        The main request handler for Pecan applications.
        '''
        cfg = _cfg(controller)
        content_types = cfg.get('content_types', {})
        req = state.request
        resp = state.response
        pecan_state = req.pecan
    
        # If a keyword is supplied via HTTP GET or POST arguments, but the
        # function signature does not allow it, just drop it (rather than
        # generating a TypeError).
        argspec = getargspec(controller)
        keys = kwargs.keys()
        for key in keys:
            if key not in argspec.args and not argspec.keywords:
                kwargs.pop(key)
    
        # get the result from the controller
>       result = controller(*args, **kwargs)
E       TypeError: TestControllerArguments.app_.<locals>.RootController.eater() missing 1 required positional argument: 'id'

pecan/core.py:574: TypeError

During handling of the above exception, another exception occurred:

self = <pecan.tests.test_base.TestControllerArguments testMethod=test_no_remainder>

    def test_no_remainder(self):
        try:
            r = self.app_.get('/eater')
            assert r.status_int != 200  # pragma: nocover
        except Exception as ex:
            assert type(ex) == TypeError
>           assert ex.args[0] in (
                "eater() takes at least 2 arguments (1 given)",
                "eater() missing 1 required positional argument: 'id'"
            )  # this messaging changed in Python 3.3
E           AssertionError: assert "TestControllerArguments.app_.<locals>.RootController.eater() missing 1 required positional argument: 'id'" in ('eater() takes at least 2 arguments (1 given)', "eater() missing 1 required positional argument: 'id'")

pecan/tests/test_base.py:996: AssertionError
________________ TestControllerArguments.test_required_argument ________________

self = <pecan.tests.test_base.TestControllerArguments testMethod=test_required_argument>

    def test_required_argument(self):
        try:
>           r = self.app_.get('/')

pecan/tests/test_base.py:453: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <webtest.app.TestApp object at 0x7f3bbbd351e0>, url = '/', params = None
headers = None, extra_environ = None, status = None, expect_errors = False
xhr = False

    def get(self, url, params=None, headers=None, extra_environ=None,
            status=None, expect_errors=False, xhr=False):
        """
        Do a GET request given the url path.
    
        :param params:
            A query string, or a dictionary that will be encoded
            into a query string.  You may also include a URL query
            string on the ``url``.
        :param headers:
            Extra headers to send.
        :type headers:
            dictionary
        :param extra_environ:
            Environmental variables that should be added to the request.
        :type extra_environ:
            dictionary
        :param status:
            The HTTP status code you expect in response (if not 200 or 3xx).
            You can also use a wildcard, like ``'3*'`` or ``'*'``.
        :type status:
            integer or string
        :param expect_errors:
            If this is False, then if anything is written to
            environ ``wsgi.errors`` it will be an error.
            If it is True, then non-200/3xx responses are also okay.
        :type expect_errors:
            boolean
        :param xhr:
            If this is true, then marks response as ajax. The same as
            headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }
        :type xhr:
            boolean
    
        :returns: :class:`webtest.TestResponse` instance.
    
        """
        environ = self._make_environ(extra_environ)
        url = str(url)
        url = self._remove_fragment(url)
        if params:
            url = utils.build_params(url, params)
        if str('?') in url:
            url, environ['QUERY_STRING'] = url.split(str('?'), 1)
        else:
            environ['QUERY_STRING'] = str('')
        req = self.RequestClass.blank(url, environ)
        if xhr:
            headers = self._add_xhr_header(headers)
        if headers:
            req.headers.update(headers)
>       return self.do_request(req, status=status,
                               expect_errors=expect_errors)

/usr/lib/python3/dist-packages/webtest/app.py:327: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <webtest.app.TestApp object at 0x7f3bbbd351e0>
req = <TestRequest at 0x7f3bbbd36800 GET http://localhost/>, status = None
expect_errors = False

    def do_request(self, req, status=None, expect_errors=None):
        """
        Executes the given webob Request (``req``), with the expected
        ``status``.  Generally :meth:`~webtest.TestApp.get` and
        :meth:`~webtest.TestApp.post` are used instead.
    
        To use this::
    
            req = webtest.TestRequest.blank('url', ...args...)
            resp = app.do_request(req)
    
        .. note::
    
            You can pass any keyword arguments to
            ``TestRequest.blank()``, which will be set on the request.
            These can be arguments like ``content_type``, ``accept``, etc.
    
        """
    
        errors = StringIO()
        req.environ['wsgi.errors'] = errors
        script_name = req.environ.get('SCRIPT_NAME', '')
        if script_name and req.path_info.startswith(script_name):
            req.path_info = req.path_info[len(script_name):]
    
        # set framework hooks
        req.environ['paste.testing'] = True
        req.environ['paste.testing_variables'] = {}
    
        # set request cookies
        self.cookiejar.add_cookie_header(utils._RequestCookieAdapter(req))
    
        # verify wsgi compatibility
        app = lint.middleware(self.app) if self.lint else self.app
    
        # FIXME: should it be an option to not catch exc_info?
>       res = req.get_response(app, catch_exc_info=True)

/usr/lib/python3/dist-packages/webtest/app.py:623: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <TestRequest at 0x7f3bbbd36800 GET http://localhost/>
application = <function middleware.<locals>.lint_app at 0x7f3bbbd5c0d0>
catch_exc_info = True

    def send(self, application=None, catch_exc_info=False):
        """
        Like ``.call_application(application)``, except returns a
        response object with ``.status``, ``.headers``, and ``.body``
        attributes.
    
        This will use ``self.ResponseClass`` to figure out the class
        of the response object to return.
    
        If ``application`` is not given, this will send the request to
        ``self.make_default_send_app()``
        """
        if application is None:
            application = self.make_default_send_app()
        if catch_exc_info:
>           status, headers, app_iter, exc_info = self.call_application(
                application, catch_exc_info=True)

/usr/lib/python3/dist-packages/webob/request.py:1309: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <TestRequest at 0x7f3bbbd36800 GET http://localhost/>
application = <function middleware.<locals>.lint_app at 0x7f3bbbd5c0d0>
catch_exc_info = True

    def call_application(self, application, catch_exc_info=False):
        """
        Call the given WSGI application, returning ``(status_string,
        headerlist, app_iter)``
    
        Be sure to call ``app_iter.close()`` if it's there.
    
        If catch_exc_info is true, then returns ``(status_string,
        headerlist, app_iter, exc_info)``, where the fourth item may
        be None, but won't be if there was an exception.  If you don't
        do this and there was an exception, the exception will be
        raised directly.
        """
        if self.is_body_seekable:
            self.body_file_raw.seek(0)
        captured = []
        output = []
        def start_response(status, headers, exc_info=None):
            if exc_info is not None and not catch_exc_info:
                reraise(exc_info)
            captured[:] = [status, headers, exc_info]
            return output.append
>       app_iter = application(self.environ, start_response)

/usr/lib/python3/dist-packages/webob/request.py:1278: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = ({'HTTP_HOST': 'localhost:80', 'PATH_INFO': '/', 'QUERY_STRING': '', 'REQUEST_METHOD': 'GET', ...}, <function BaseRequest.call_application.<locals>.start_response at 0x7f3bbbca6e60>)
kw = {}
environ = {'HTTP_HOST': 'localhost:80', 'PATH_INFO': '/', 'QUERY_STRING': '', 'REQUEST_METHOD': 'GET', ...}
start_response_wrapper = <function middleware.<locals>.lint_app.<locals>.start_response_wrapper at 0x7f3bbbca6ef0>

    def lint_app(*args, **kw):
        assert len(args) == 2, "Two arguments required"
        assert not kw, "No keyword arguments allowed"
        environ, start_response = args
    
        check_environ(environ)
    
        # We use this to check if the application returns without
        # calling start_response:
        start_response_started = []
    
        def start_response_wrapper(*args, **kw):
            assert len(args) == 2 or len(args) == 3, (
                "Invalid number of arguments: %s" % args)
            assert not kw, "No keyword arguments allowed"
            status = args[0]
            headers = args[1]
            if len(args) == 3:
                exc_info = args[2]
            else:
                exc_info = None
    
            check_status(status)
            check_headers(headers)
            check_content_type(status, headers)
            check_exc_info(exc_info)
    
            start_response_started.append(None)
            return WriteWrapper(start_response(*args))
    
        environ['wsgi.input'] = InputWrapper(environ['wsgi.input'])
        environ['wsgi.errors'] = ErrorWrapper(environ['wsgi.errors'])
    
>       iterator = application(environ, start_response_wrapper)

/usr/lib/python3/dist-packages/webtest/lint.py:201: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pecan.core.Pecan object at 0x7f3bbbd34f10>
environ = {'HTTP_HOST': 'localhost:80', 'PATH_INFO': '/', 'QUERY_STRING': '', 'REQUEST_METHOD': 'GET', ...}
start_response = <function middleware.<locals>.lint_app.<locals>.start_response_wrapper at 0x7f3bbbca6ef0>

    def __call__(self, environ, start_response):
        try:
            state.hooks = []
            state.app = self
            state.controller = None
            state.arguments = None
>           return super(Pecan, self).__call__(environ, start_response)

pecan/core.py:840: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pecan.core.Pecan object at 0x7f3bbbd34f10>
environ = {'HTTP_HOST': 'localhost:80', 'PATH_INFO': '/', 'QUERY_STRING': '', 'REQUEST_METHOD': 'GET', ...}
start_response = <function middleware.<locals>.lint_app.<locals>.start_response_wrapper at 0x7f3bbbca6ef0>

    def __call__(self, environ, start_response):
        '''
        Implements the WSGI specification for Pecan applications, utilizing
        ``WebOb``.
        '''
    
        # create the request and response object
        req = self.request_cls(environ)
        resp = self.response_cls()
        state = RoutingState(req, resp, self)
        environ['pecan.locals'] = {
            'request': req,
            'response': resp
        }
        controller = None
    
        # track internal redirects
        internal_redirect = False
    
        # handle the request
        try:
            # add context and environment to the request
            req.context = environ.get('pecan.recursive.context', {})
            req.pecan = dict(content_type=None)
    
            controller, args, kwargs = self.find_controller(state)
>           self.invoke_controller(controller, args, kwargs, state)

pecan/core.py:683: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pecan.core.Pecan object at 0x7f3bbbd34f10>
controller = <bound method TestControllerArguments.app_.<locals>.RootController.index of <pecan.tests.test_base.TestControllerArguments.app_.<locals>.RootController object at 0x7f3bbbd3c790>>
args = [], kwargs = {}
state = <pecan.core.RoutingState object at 0x7f3bbbd355a0>

    def invoke_controller(self, controller, args, kwargs, state):
        '''
        The main request handler for Pecan applications.
        '''
        cfg = _cfg(controller)
        content_types = cfg.get('content_types', {})
        req = state.request
        resp = state.response
        pecan_state = req.pecan
    
        # If a keyword is supplied via HTTP GET or POST arguments, but the
        # function signature does not allow it, just drop it (rather than
        # generating a TypeError).
        argspec = getargspec(controller)
        keys = kwargs.keys()
        for key in keys:
            if key not in argspec.args and not argspec.keywords:
                kwargs.pop(key)
    
        # get the result from the controller
>       result = controller(*args, **kwargs)
E       TypeError: TestControllerArguments.app_.<locals>.RootController.index() missing 1 required positional argument: 'id'

pecan/core.py:574: TypeError

During handling of the above exception, another exception occurred:

self = <pecan.tests.test_base.TestControllerArguments testMethod=test_required_argument>

    def test_required_argument(self):
        try:
            r = self.app_.get('/')
            assert r.status_int != 200  # pragma: nocover
        except Exception as ex:
            assert type(ex) == TypeError
>           assert ex.args[0] in (
                "index() takes exactly 2 arguments (1 given)",
                "index() missing 1 required positional argument: 'id'"
            )  # this messaging changed in Python 3.3
E           AssertionError: assert "TestControllerArguments.app_.<locals>.RootController.index() missing 1 required positional argument: 'id'" in ('index() takes exactly 2 arguments (1 given)', "index() missing 1 required positional argument: 'id'")

pecan/tests/test_base.py:457: AssertionError
__________________ TestControllerArguments.test_no_remainder ___________________

self = <pecan.tests.test_no_thread_locals.TestControllerArguments testMethod=test_no_remainder>

    def test_no_remainder(self):
        try:
>           r = self.app_.get('/eater')

pecan/tests/test_no_thread_locals.py:761: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <webtest.app.TestApp object at 0x7f3bbb251030>, url = '/eater'
params = None, headers = None, extra_environ = None, status = None
expect_errors = False, xhr = False

    def get(self, url, params=None, headers=None, extra_environ=None,
            status=None, expect_errors=False, xhr=False):
        """
        Do a GET request given the url path.
    
        :param params:
            A query string, or a dictionary that will be encoded
            into a query string.  You may also include a URL query
            string on the ``url``.
        :param headers:
            Extra headers to send.
        :type headers:
            dictionary
        :param extra_environ:
            Environmental variables that should be added to the request.
        :type extra_environ:
            dictionary
        :param status:
            The HTTP status code you expect in response (if not 200 or 3xx).
            You can also use a wildcard, like ``'3*'`` or ``'*'``.
        :type status:
            integer or string
        :param expect_errors:
            If this is False, then if anything is written to
            environ ``wsgi.errors`` it will be an error.
            If it is True, then non-200/3xx responses are also okay.
        :type expect_errors:
            boolean
        :param xhr:
            If this is true, then marks response as ajax. The same as
            headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }
        :type xhr:
            boolean
    
        :returns: :class:`webtest.TestResponse` instance.
    
        """
        environ = self._make_environ(extra_environ)
        url = str(url)
        url = self._remove_fragment(url)
        if params:
            url = utils.build_params(url, params)
        if str('?') in url:
            url, environ['QUERY_STRING'] = url.split(str('?'), 1)
        else:
            environ['QUERY_STRING'] = str('')
        req = self.RequestClass.blank(url, environ)
        if xhr:
            headers = self._add_xhr_header(headers)
        if headers:
            req.headers.update(headers)
>       return self.do_request(req, status=status,
                               expect_errors=expect_errors)

/usr/lib/python3/dist-packages/webtest/app.py:327: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <webtest.app.TestApp object at 0x7f3bbb251030>
req = <TestRequest at 0x7f3bbb250f70 GET http://localhost/eater>, status = None
expect_errors = False

    def do_request(self, req, status=None, expect_errors=None):
        """
        Executes the given webob Request (``req``), with the expected
        ``status``.  Generally :meth:`~webtest.TestApp.get` and
        :meth:`~webtest.TestApp.post` are used instead.
    
        To use this::
    
            req = webtest.TestRequest.blank('url', ...args...)
            resp = app.do_request(req)
    
        .. note::
    
            You can pass any keyword arguments to
            ``TestRequest.blank()``, which will be set on the request.
            These can be arguments like ``content_type``, ``accept``, etc.
    
        """
    
        errors = StringIO()
        req.environ['wsgi.errors'] = errors
        script_name = req.environ.get('SCRIPT_NAME', '')
        if script_name and req.path_info.startswith(script_name):
            req.path_info = req.path_info[len(script_name):]
    
        # set framework hooks
        req.environ['paste.testing'] = True
        req.environ['paste.testing_variables'] = {}
    
        # set request cookies
        self.cookiejar.add_cookie_header(utils._RequestCookieAdapter(req))
    
        # verify wsgi compatibility
        app = lint.middleware(self.app) if self.lint else self.app
    
        # FIXME: should it be an option to not catch exc_info?
>       res = req.get_response(app, catch_exc_info=True)

/usr/lib/python3/dist-packages/webtest/app.py:623: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <TestRequest at 0x7f3bbb250f70 GET http://localhost/eater>
application = <function middleware.<locals>.lint_app at 0x7f3bbb233be0>
catch_exc_info = True

    def send(self, application=None, catch_exc_info=False):
        """
        Like ``.call_application(application)``, except returns a
        response object with ``.status``, ``.headers``, and ``.body``
        attributes.
    
        This will use ``self.ResponseClass`` to figure out the class
        of the response object to return.
    
        If ``application`` is not given, this will send the request to
        ``self.make_default_send_app()``
        """
        if application is None:
            application = self.make_default_send_app()
        if catch_exc_info:
>           status, headers, app_iter, exc_info = self.call_application(
                application, catch_exc_info=True)

/usr/lib/python3/dist-packages/webob/request.py:1309: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <TestRequest at 0x7f3bbb250f70 GET http://localhost/eater>
application = <function middleware.<locals>.lint_app at 0x7f3bbb233be0>
catch_exc_info = True

    def call_application(self, application, catch_exc_info=False):
        """
        Call the given WSGI application, returning ``(status_string,
        headerlist, app_iter)``
    
        Be sure to call ``app_iter.close()`` if it's there.
    
        If catch_exc_info is true, then returns ``(status_string,
        headerlist, app_iter, exc_info)``, where the fourth item may
        be None, but won't be if there was an exception.  If you don't
        do this and there was an exception, the exception will be
        raised directly.
        """
        if self.is_body_seekable:
            self.body_file_raw.seek(0)
        captured = []
        output = []
        def start_response(status, headers, exc_info=None):
            if exc_info is not None and not catch_exc_info:
                reraise(exc_info)
            captured[:] = [status, headers, exc_info]
            return output.append
>       app_iter = application(self.environ, start_response)

/usr/lib/python3/dist-packages/webob/request.py:1278: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = ({'HTTP_HOST': 'localhost:80', 'PATH_INFO': '/eater', 'QUERY_STRING': '', 'REQUEST_METHOD': 'GET', ...}, <function BaseRequest.call_application.<locals>.start_response at 0x7f3bbb24d900>)
kw = {}
environ = {'HTTP_HOST': 'localhost:80', 'PATH_INFO': '/eater', 'QUERY_STRING': '', 'REQUEST_METHOD': 'GET', ...}
start_response_wrapper = <function middleware.<locals>.lint_app.<locals>.start_response_wrapper at 0x7f3bbb24d990>

    def lint_app(*args, **kw):
        assert len(args) == 2, "Two arguments required"
        assert not kw, "No keyword arguments allowed"
        environ, start_response = args
    
        check_environ(environ)
    
        # We use this to check if the application returns without
        # calling start_response:
        start_response_started = []
    
        def start_response_wrapper(*args, **kw):
            assert len(args) == 2 or len(args) == 3, (
                "Invalid number of arguments: %s" % args)
            assert not kw, "No keyword arguments allowed"
            status = args[0]
            headers = args[1]
            if len(args) == 3:
                exc_info = args[2]
            else:
                exc_info = None
    
            check_status(status)
            check_headers(headers)
            check_content_type(status, headers)
            check_exc_info(exc_info)
    
            start_response_started.append(None)
            return WriteWrapper(start_response(*args))
    
        environ['wsgi.input'] = InputWrapper(environ['wsgi.input'])
        environ['wsgi.errors'] = ErrorWrapper(environ['wsgi.errors'])
    
>       iterator = application(environ, start_response_wrapper)

/usr/lib/python3/dist-packages/webtest/lint.py:201: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pecan.core.ExplicitPecan object at 0x7f3bbb2266e0>
environ = {'HTTP_HOST': 'localhost:80', 'PATH_INFO': '/eater', 'QUERY_STRING': '', 'REQUEST_METHOD': 'GET', ...}
start_response = <function middleware.<locals>.lint_app.<locals>.start_response_wrapper at 0x7f3bbb24d990>

    def __call__(self, environ, start_response):
        '''
        Implements the WSGI specification for Pecan applications, utilizing
        ``WebOb``.
        '''
    
        # create the request and response object
        req = self.request_cls(environ)
        resp = self.response_cls()
        state = RoutingState(req, resp, self)
        environ['pecan.locals'] = {
            'request': req,
            'response': resp
        }
        controller = None
    
        # track internal redirects
        internal_redirect = False
    
        # handle the request
        try:
            # add context and environment to the request
            req.context = environ.get('pecan.recursive.context', {})
            req.pecan = dict(content_type=None)
    
            controller, args, kwargs = self.find_controller(state)
>           self.invoke_controller(controller, args, kwargs, state)

pecan/core.py:683: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pecan.core.ExplicitPecan object at 0x7f3bbb2266e0>
controller = <bound method TestControllerArguments.app_.<locals>.RootController.eater of <pecan.tests.test_no_thread_locals.TestControllerArguments.app_.<locals>.RootController object at 0x7f3bbb225030>>
args = [<Request at 0x7f3bbb250190 GET http://localhost/eater>, <Response at 0x7f3bbb2506d0 200 OK>]
kwargs = {}, state = <pecan.core.RoutingState object at 0x7f3bbb250520>

    def invoke_controller(self, controller, args, kwargs, state):
        '''
        The main request handler for Pecan applications.
        '''
        cfg = _cfg(controller)
        content_types = cfg.get('content_types', {})
        req = state.request
        resp = state.response
        pecan_state = req.pecan
    
        # If a keyword is supplied via HTTP GET or POST arguments, but the
        # function signature does not allow it, just drop it (rather than
        # generating a TypeError).
        argspec = getargspec(controller)
        keys = kwargs.keys()
        for key in keys:
            if key not in argspec.args and not argspec.keywords:
                kwargs.pop(key)
    
        # get the result from the controller
>       result = controller(*args, **kwargs)
E       TypeError: TestControllerArguments.app_.<locals>.RootController.eater() missing 1 required positional argument: 'id'

pecan/core.py:574: TypeError

During handling of the above exception, another exception occurred:

self = <pecan.tests.test_no_thread_locals.TestControllerArguments testMethod=test_no_remainder>

    def test_no_remainder(self):
        try:
            r = self.app_.get('/eater')
            assert r.status_int != 200  # pragma: nocover
        except Exception as ex:
            assert type(ex) == TypeError
>           assert ex.args[0] in (
                "eater() takes at least 4 arguments (3 given)",
                "eater() missing 1 required positional argument: 'id'"
            )  # this messaging changed in Python 3.3
E           AssertionError: assert "TestControllerArguments.app_.<locals>.RootController.eater() missing 1 required positional argument: 'id'" in ('eater() takes at least 4 arguments (3 given)', "eater() missing 1 required positional argument: 'id'")

pecan/tests/test_no_thread_locals.py:765: AssertionError
________________ TestControllerArguments.test_required_argument ________________

self = <pecan.tests.test_no_thread_locals.TestControllerArguments testMethod=test_required_argument>

    def test_required_argument(self):
        try:
>           r = self.app_.get('/')

pecan/tests/test_no_thread_locals.py:359: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <webtest.app.TestApp object at 0x7f3bbb09e3b0>, url = '/', params = None
headers = None, extra_environ = None, status = None, expect_errors = False
xhr = False

    def get(self, url, params=None, headers=None, extra_environ=None,
            status=None, expect_errors=False, xhr=False):
        """
        Do a GET request given the url path.
    
        :param params:
            A query string, or a dictionary that will be encoded
            into a query string.  You may also include a URL query
            string on the ``url``.
        :param headers:
            Extra headers to send.
        :type headers:
            dictionary
        :param extra_environ:
            Environmental variables that should be added to the request.
        :type extra_environ:
            dictionary
        :param status:
            The HTTP status code you expect in response (if not 200 or 3xx).
            You can also use a wildcard, like ``'3*'`` or ``'*'``.
        :type status:
            integer or string
        :param expect_errors:
            If this is False, then if anything is written to
            environ ``wsgi.errors`` it will be an error.
            If it is True, then non-200/3xx responses are also okay.
        :type expect_errors:
            boolean
        :param xhr:
            If this is true, then marks response as ajax. The same as
            headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }
        :type xhr:
            boolean
    
        :returns: :class:`webtest.TestResponse` instance.
    
        """
        environ = self._make_environ(extra_environ)
        url = str(url)
        url = self._remove_fragment(url)
        if params:
            url = utils.build_params(url, params)
        if str('?') in url:
            url, environ['QUERY_STRING'] = url.split(str('?'), 1)
        else:
            environ['QUERY_STRING'] = str('')
        req = self.RequestClass.blank(url, environ)
        if xhr:
            headers = self._add_xhr_header(headers)
        if headers:
            req.headers.update(headers)
>       return self.do_request(req, status=status,
                               expect_errors=expect_errors)

/usr/lib/python3/dist-packages/webtest/app.py:327: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <webtest.app.TestApp object at 0x7f3bbb09e3b0>
req = <TestRequest at 0x7f3bbb4050c0 GET http://localhost/>, status = None
expect_errors = False

    def do_request(self, req, status=None, expect_errors=None):
        """
        Executes the given webob Request (``req``), with the expected
        ``status``.  Generally :meth:`~webtest.TestApp.get` and
        :meth:`~webtest.TestApp.post` are used instead.
    
        To use this::
    
            req = webtest.TestRequest.blank('url', ...args...)
            resp = app.do_request(req)
    
        .. note::
    
            You can pass any keyword arguments to
            ``TestRequest.blank()``, which will be set on the request.
            These can be arguments like ``content_type``, ``accept``, etc.
    
        """
    
        errors = StringIO()
        req.environ['wsgi.errors'] = errors
        script_name = req.environ.get('SCRIPT_NAME', '')
        if script_name and req.path_info.startswith(script_name):
            req.path_info = req.path_info[len(script_name):]
    
        # set framework hooks
        req.environ['paste.testing'] = True
        req.environ['paste.testing_variables'] = {}
    
        # set request cookies
        self.cookiejar.add_cookie_header(utils._RequestCookieAdapter(req))
    
        # verify wsgi compatibility
        app = lint.middleware(self.app) if self.lint else self.app
    
        # FIXME: should it be an option to not catch exc_info?
>       res = req.get_response(app, catch_exc_info=True)

/usr/lib/python3/dist-packages/webtest/app.py:623: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <TestRequest at 0x7f3bbb4050c0 GET http://localhost/>
application = <function middleware.<locals>.lint_app at 0x7f3bbb2d0dc0>
catch_exc_info = True

    def send(self, application=None, catch_exc_info=False):
        """
        Like ``.call_application(application)``, except returns a
        response object with ``.status``, ``.headers``, and ``.body``
        attributes.
    
        This will use ``self.ResponseClass`` to figure out the class
        of the response object to return.
    
        If ``application`` is not given, this will send the request to
        ``self.make_default_send_app()``
        """
        if application is None:
            application = self.make_default_send_app()
        if catch_exc_info:
>           status, headers, app_iter, exc_info = self.call_application(
                application, catch_exc_info=True)

/usr/lib/python3/dist-packages/webob/request.py:1309: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <TestRequest at 0x7f3bbb4050c0 GET http://localhost/>
application = <function middleware.<locals>.lint_app at 0x7f3bbb2d0dc0>
catch_exc_info = True

    def call_application(self, application, catch_exc_info=False):
        """
        Call the given WSGI application, returning ``(status_string,
        headerlist, app_iter)``
    
        Be sure to call ``app_iter.close()`` if it's there.
    
        If catch_exc_info is true, then returns ``(status_string,
        headerlist, app_iter, exc_info)``, where the fourth item may
        be None, but won't be if there was an exception.  If you don't
        do this and there was an exception, the exception will be
        raised directly.
        """
        if self.is_body_seekable:
            self.body_file_raw.seek(0)
        captured = []
        output = []
        def start_response(status, headers, exc_info=None):
            if exc_info is not None and not catch_exc_info:
                reraise(exc_info)
            captured[:] = [status, headers, exc_info]
            return output.append
>       app_iter = application(self.environ, start_response)

/usr/lib/python3/dist-packages/webob/request.py:1278: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = ({'HTTP_HOST': 'localhost:80', 'PATH_INFO': '/', 'QUERY_STRING': '', 'REQUEST_METHOD': 'GET', ...}, <function BaseRequest.call_application.<locals>.start_response at 0x7f3bbb0a1120>)
kw = {}
environ = {'HTTP_HOST': 'localhost:80', 'PATH_INFO': '/', 'QUERY_STRING': '', 'REQUEST_METHOD': 'GET', ...}
start_response_wrapper = <function middleware.<locals>.lint_app.<locals>.start_response_wrapper at 0x7f3bbb0a11b0>

    def lint_app(*args, **kw):
        assert len(args) == 2, "Two arguments required"
        assert not kw, "No keyword arguments allowed"
        environ, start_response = args
    
        check_environ(environ)
    
        # We use this to check if the application returns without
        # calling start_response:
        start_response_started = []
    
        def start_response_wrapper(*args, **kw):
            assert len(args) == 2 or len(args) == 3, (
                "Invalid number of arguments: %s" % args)
            assert not kw, "No keyword arguments allowed"
            status = args[0]
            headers = args[1]
            if len(args) == 3:
                exc_info = args[2]
            else:
                exc_info = None
    
            check_status(status)
            check_headers(headers)
            check_content_type(status, headers)
            check_exc_info(exc_info)
    
            start_response_started.append(None)
            return WriteWrapper(start_response(*args))
    
        environ['wsgi.input'] = InputWrapper(environ['wsgi.input'])
        environ['wsgi.errors'] = ErrorWrapper(environ['wsgi.errors'])
    
>       iterator = application(environ, start_response_wrapper)

/usr/lib/python3/dist-packages/webtest/lint.py:201: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pecan.core.ExplicitPecan object at 0x7f3bbb090340>
environ = {'HTTP_HOST': 'localhost:80', 'PATH_INFO': '/', 'QUERY_STRING': '', 'REQUEST_METHOD': 'GET', ...}
start_response = <function middleware.<locals>.lint_app.<locals>.start_response_wrapper at 0x7f3bbb0a11b0>

    def __call__(self, environ, start_response):
        '''
        Implements the WSGI specification for Pecan applications, utilizing
        ``WebOb``.
        '''
    
        # create the request and response object
        req = self.request_cls(environ)
        resp = self.response_cls()
        state = RoutingState(req, resp, self)
        environ['pecan.locals'] = {
            'request': req,
            'response': resp
        }
        controller = None
    
        # track internal redirects
        internal_redirect = False
    
        # handle the request
        try:
            # add context and environment to the request
            req.context = environ.get('pecan.recursive.context', {})
            req.pecan = dict(content_type=None)
    
            controller, args, kwargs = self.find_controller(state)
>           self.invoke_controller(controller, args, kwargs, state)

pecan/core.py:683: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pecan.core.ExplicitPecan object at 0x7f3bbb090340>
controller = <bound method TestControllerArguments.app_.<locals>.RootController.index of <pecan.tests.test_no_thread_locals.TestControllerArguments.app_.<locals>.RootController object at 0x7f3bbb093340>>
args = [<Request at 0x7f3bbb09d960 GET http://localhost/>, <Response at 0x7f3bbb09d120 200 OK>]
kwargs = {}, state = <pecan.core.RoutingState object at 0x7f3bbb09c8b0>

    def invoke_controller(self, controller, args, kwargs, state):
        '''
        The main request handler for Pecan applications.
        '''
        cfg = _cfg(controller)
        content_types = cfg.get('content_types', {})
        req = state.request
        resp = state.response
        pecan_state = req.pecan
    
        # If a keyword is supplied via HTTP GET or POST arguments, but the
        # function signature does not allow it, just drop it (rather than
        # generating a TypeError).
        argspec = getargspec(controller)
        keys = kwargs.keys()
        for key in keys:
            if key not in argspec.args and not argspec.keywords:
                kwargs.pop(key)
    
        # get the result from the controller
>       result = controller(*args, **kwargs)
E       TypeError: TestControllerArguments.app_.<locals>.RootController.index() missing 1 required positional argument: 'id'

pecan/core.py:574: TypeError

During handling of the above exception, another exception occurred:

self = <pecan.tests.test_no_thread_locals.TestControllerArguments testMethod=test_required_argument>

    def test_required_argument(self):
        try:
            r = self.app_.get('/')
            assert r.status_int != 200  # pragma: nocover
        except Exception as ex:
            assert type(ex) == TypeError
>           assert ex.args[0] in (
                "index() takes exactly 4 arguments (3 given)",
                "index() missing 1 required positional argument: 'id'"
            )  # this messaging changed in Python 3.3
E           AssertionError: assert "TestControllerArguments.app_.<locals>.RootController.index() missing 1 required positional argument: 'id'" in ('index() takes exactly 4 arguments (3 given)', "index() missing 1 required positional argument: 'id'")

pecan/tests/test_no_thread_locals.py:363: AssertionError

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants