Tribler / tribler

Privacy enhanced BitTorrent client with P2P content discovery
https://www.tribler.org
GNU General Public License v3.0
4.85k stars 450 forks source link

[7.6.0 on Arch Linux] schema2parameters() missing 1 required keyword-only argument: 'location' #5814

Closed Houkime closed 2 years ago

Houkime commented 3 years ago

Please, fill all relevant items:

Tribler version/branch+revision:

branch: release-7.6 commit: 0c841fdf36e5497231f6f79d5451e74163a48ac3

Operating system and version:

Arch Linux, 5.9.11 kernel (aiohttp 3.7.3 aiohttp-apispec 2.2.1 apispec 4.0.0)

Steps to reproduce the behavior:
Expected behavior:

Tribler starts

Actual behavior:

Crash before booting up

Relevant log file output:
[PID:1002] 2020-12-06 08:33:10,754 - INFO - root(24) - __init__()
[PID:1002] 2020-12-06 08:33:10,850 - INFO - root(50) -   self._outSocket.error() = '2'
[PID:1002] 2020-12-06 08:33:10,850 - INFO - root(60) - __init__(): returning
[PID:1002] 2020-12-06 08:33:12,245 - INFO - TriblerGUI(126) - Will connect to events endpoint
[PID:1002] 2020-12-06 08:33:12,619 - INFO - TriblerGUI(68) - Got Tribler core error: 1
[PID:1002] 2020-12-06 08:33:13,095 - INFO - TriblerGUI(126) - Will connect to events endpoint
[PID:1002] 2020-12-06 08:33:13,097 - INFO - TriblerGUI(68) - Got Tribler core error: 1
[PID:1002] 2020-12-06 08:33:13,572 - INFO - TriblerGUI(126) - Will connect to events endpoint
[PID:1002] 2020-12-06 08:33:13,573 - INFO - TriblerGUI(68) - Got Tribler core error: 1
[PID:1024] 2020-12-06 08:33:13,854 - INFO - Session(279) - Session is using state directory: /home/user/.Tribler/7.6
[PID:1002] 2020-12-06 08:33:14,049 - INFO - TriblerGUI(126) - Will connect to events endpoint
[PID:1002] 2020-12-06 08:33:14,050 - INFO - TriblerGUI(68) - Got Tribler core error: 1
[PID:1024] 2020-12-06 08:33:14,377 - ERROR <session:249> Session.unhandled_error_observer(): Unhandled exception occurred! schema2parameters() missing 1 required keyword-only argument: 'location'
--LONG TEXT--
Traceback (most recent call last):
  File "/home/user/tribler/src/run_tribler.py", line 84, in start_tribler
    await session.start()
  File "/home/user/tribler/src/tribler-core/tribler_core/session.py", line 289, in start
    await self.api_manager.start()
  File "/home/user/tribler/src/tribler-core/tribler_core/restapi/rest_manager.py", line 102, in start
    await self.runner.setup()
  File "/usr/lib/python3.9/site-packages/aiohttp/web_runner.py", line 275, in setup
    self._server = await self._make_server()
  File "/usr/lib/python3.9/site-packages/aiohttp/web_runner.py", line 375, in _make_server
    await self._app.startup()
  File "/usr/lib/python3.9/site-packages/aiohttp/web_app.py", line 416, in startup
    await self.on_startup.send(self)
  File "/usr/lib/python3.9/site-packages/aiohttp/signals.py", line 34, in send
    await receiver(*args, **kwargs)  # type: ignore
  File "/usr/lib/python3.9/site-packages/aiohttp_apispec/aiohttp_apispec.py", line 77, in doc_routes
    self._register(app_)
  File "/usr/lib/python3.9/site-packages/aiohttp_apispec/aiohttp_apispec.py", line 117, in _register
    self._register_route(route, method, view)
  File "/usr/lib/python3.9/site-packages/aiohttp_apispec/aiohttp_apispec.py", line 131, in _register_route
    self._update_paths(view.__apispec__, method, self.prefix + url_path)
  File "/usr/lib/python3.9/site-packages/aiohttp_apispec/aiohttp_apispec.py", line 153, in _update_paths
    raw_parameters = self.plugin.converter.schema2parameters(
TypeError: schema2parameters() missing 1 required keyword-only argument: 'location'  
Houkime commented 3 years ago

Extra info: aiohttp 3.7.3 (added to the top also) aiohttp-apispec 2.2.1

Houkime commented 3 years ago
    def schema2parameters(
        self, schema, *, location, name="body", required=False, description=None
    ):
        """Return an array of OpenAPI parameters given a given marshmallow
        :class:`Schema <marshmallow.Schema>`. If `location` is "body", then return an array
        of a single parameter; else return an array of a parameter for each included field in
        the :class:`Schema <marshmallow.Schema>`.

        In OpenAPI 3, only "query", "header", "path" or "cookie" are allowed for the location
        of parameters. "requestBody" is used when fields are in the body.

        https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#parameterObject
        """
        location = __location_map__.get(location, location)
        # OAS 2 body parameter
        if location == "body":
            param = {
                "in": location,
                "required": required,
                "name": name,
                "schema": self.resolve_nested_schema(schema),
            }
            if description:
                param["description"] = description
            return [param]

        assert not getattr(
            schema, "many", False
        ), "Schemas with many=True are only supported for 'json' location (aka 'in: body')"

        fields = get_fields(schema, exclude_dump_only=True)

        return [
            self._field2parameter(
                field_obj, name=field_obj.data_key or field_name, location=location,
            )
            for field_name, field_obj in fields.items()
        ]

While the code calling for it in aiohttp_apispec.py looks like this.

        if "responses" in data:
            responses = {}
            for code, actual_params in data["responses"].items():
                if "schema" in actual_params:
                    raw_parameters = self.plugin.converter.schema2parameters(
                        actual_params["schema"],
                        required=actual_params.get("required", False),
                    )[0]
                    updated_params = {
                        k: v
                        for k, v in raw_parameters.items()
                        if k in VALID_RESPONSE_FIELDS
                    }
                    updated_params['schema'] = actual_params["schema"]
                    for extra_info in ("description", "headers", "examples"):
                        if extra_info in actual_params:
                            updated_params[extra_info] = actual_params[extra_info]
                    responses[code] = updated_params
                else:
                    responses[code] = actual_params
            data["responses"] = responses

So, it looks like a version incompatibility between the aiohttp_apispec and apispec, which most probably has occured when apispec turned 4.0.0.

Houkime commented 3 years ago

this incompatibility was introduced by https://github.com/marshmallow-code/apispec/commit/ee8002b466aeebb753bdf93047198b3ff63f02d0 and indeed was included in 4.0.0 onwards.

Houkime commented 3 years ago

This probably needs to be fixed at aiohttp_apispec side. Opened an issue there. https://github.com/maximdanilchenko/aiohttp-apispec/issues/105

Houkime commented 3 years ago

aiohttp_apispec requirements.txt forbids using apispec 4+ and is not officially ready for it. As it seems, this bug was made possible by Arch Linux package https://www.archlinux.org/packages/community/any/python-aiohttp-apispec/ not having upper version bounds on dependencies (which bounds are discouraged on a rolling release system) Notified package maintainer.

pip install --user aiohttp_apispec (or using a virtual environment) seems to fix the problem at least temporarily.

qstokkink commented 3 years ago

Thanks for both reporting and diving into this issue. This would've been a pain to debug on our side as none of our core developers really use Arch on a daily basis.

We'll keep an eye out on the upstream issues. Please let us know if we can help you out in any way.

kozlovsky commented 3 years ago

If we explicitly add apispec>=3.2.4, <4.0 to requirements.txt, should it solve the problem on Arch Linux until the Arch Linux package is fixed?

Houkime commented 3 years ago

I don't think it will make a difference. If installing aiohttp_apispec via pip, apispec 4 is already forbidden, so a lower version will be selected. If installing via pacman, deps and conflicts will be checked as per PKGBUILDs and ignore requirements.txt

On the plus side, aiohttp_apispec is fairly small, so once @maximdanilchenko or another upstream maintainer is back the apispec 4 compatibility might happen fast. If a new aiohttp_apispec release is made upstream, propagating an update to Arch packages is usually fast.

Houkime commented 3 years ago

Also, if someone makes a quick fix to aiohttp_apispec, it technically can be applied to the Arch package right away even before upstream reacts to a PR.

sentry-for-tribler[bot] commented 3 years ago

Sentry issue: TRIBLER-2V

RunningDroid commented 2 years ago

https://github.com/maximdanilchenko/aiohttp-apispec/issues/105 has been closed by https://github.com/maximdanilchenko/aiohttp-apispec/pull/115, this bug can probably be closed as well

kozlovsky commented 2 years ago

Great to hear that!