)]}'
{"ironicclient/common/base.py":[{"author":{"_account_id":10342,"name":"Jay Faulkner","display_name":"JayF","email":"jay@jvf.cc","username":"JayF","status":"youtube.com/@oss-gr / podcast.gr-oss.io"},"change_message_id":"74e9a769428aed791d68dd12320a46d712aeb95d","unresolved":true,"context_lines":[{"line_number":208,"context_line":"        limit_reached \u003d False"},{"line_number":209,"context_line":"        while url:"},{"line_number":210,"context_line":"            resp, body \u003d self.api.json_request(\u0027GET\u0027, url, **kwargs)"},{"line_number":211,"context_line":"            assert isinstance(body, dict)"},{"line_number":212,"context_line":"            data \u003d self._format_body_data(body, response_key)"},{"line_number":213,"context_line":"            for obj in data:"},{"line_number":214,"context_line":"                item \u003d obj_class("}],"source_content_type":"text/x-python","patch_set":3,"id":"94555541_6c7928da","line":211,"updated":"2026-03-11 15:01:12.000000000","message":"There\u0027s almost never a good reason to have an assert in codepaths. Why are we adding some in this file?","commit_id":"3d730a6025a633da49f40f9d9abddf9efcd46316"},{"author":{"_account_id":38828,"name":"Karan Anand","display_name":"Karan","email":"anandkarancompsci@gmail.com","username":"anandkaranubc"},"change_message_id":"3945f6a6f61ce3b90025c1b8066f99b4cf21e974","unresolved":true,"context_lines":[{"line_number":208,"context_line":"        limit_reached \u003d False"},{"line_number":209,"context_line":"        while url:"},{"line_number":210,"context_line":"            resp, body \u003d self.api.json_request(\u0027GET\u0027, url, **kwargs)"},{"line_number":211,"context_line":"            if not isinstance(body, dict):"},{"line_number":212,"context_line":"                raise exc.InvalidAttribute("},{"line_number":213,"context_line":"                    \u0027API response body must be a JSON object; got %s\u0027 %"},{"line_number":214,"context_line":"                    type(body).__name__)"}],"source_content_type":"text/x-python","patch_set":5,"id":"ca8a7311_18a35a5a","line":211,"updated":"2026-03-15 02:25:36.000000000","message":"This check is there so we fail fast with a clear error when the API doesn’t return a JSON object. The code below assumes body is a dict (e.g. body.get(\u0027next\u0027), _format_body_data(body, ...)). If the server returns a list or nothing, we’d get a confusing AttributeError later.\n\nfor mypy, it narrows the type so that after the check the type checker know body is a dict in that block.","commit_id":"5cc86db4336a4a1cb44bb2065ee257a8d75be8e6"},{"author":{"_account_id":10342,"name":"Jay Faulkner","display_name":"JayF","email":"jay@jvf.cc","username":"JayF","status":"youtube.com/@oss-gr / podcast.gr-oss.io"},"change_message_id":"2f7af78abd2c3b57731cbe05605a963c2cee1d20","unresolved":true,"context_lines":[{"line_number":208,"context_line":"        limit_reached \u003d False"},{"line_number":209,"context_line":"        while url:"},{"line_number":210,"context_line":"            resp, body \u003d self.api.json_request(\u0027GET\u0027, url, **kwargs)"},{"line_number":211,"context_line":"            if not isinstance(body, dict):"},{"line_number":212,"context_line":"                raise exc.InvalidAttribute("},{"line_number":213,"context_line":"                    \u0027API response body must be a JSON object; got %s\u0027 %"},{"line_number":214,"context_line":"                    type(body).__name__)"}],"source_content_type":"text/x-python","patch_set":5,"id":"cdb2400c_4abdad39","line":211,"in_reply_to":"ca8a7311_18a35a5a","updated":"2026-03-18 15:37:09.000000000","message":"Ideally you\u0027d put this statement (maybe a less verbose version of it) in a code comment next time.","commit_id":"5cc86db4336a4a1cb44bb2065ee257a8d75be8e6"}],"ironicclient/common/http.py":[{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"4bc66fea3b1c33d5f031a052e324d7fca14afd6b","unresolved":true,"context_lines":[{"line_number":31,"context_line":"from keystoneauth1 import adapter"},{"line_number":32,"context_line":"from keystoneauth1 import exceptions as kexc"},{"line_number":33,"context_line":"from keystoneauth1 import session as ks_session"},{"line_number":34,"context_line":"import requests  # type: ignore[import-untyped]  # no upstream type stubs"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"from ironicclient.common import filecache"},{"line_number":37,"context_line":"from ironicclient.common.i18n import _"}],"source_content_type":"text/x-python","patch_set":5,"id":"89e7bf1d_46055d7e","line":34,"updated":"2026-03-19 11:05:08.000000000","message":"You want https://pypi.org/project/types-requests/","commit_id":"5cc86db4336a4a1cb44bb2065ee257a8d75be8e6"},{"author":{"_account_id":38828,"name":"Karan Anand","display_name":"Karan","email":"anandkarancompsci@gmail.com","username":"anandkaranubc"},"change_message_id":"d175fc3090e68b7e4cf38e57b407ab893c60600f","unresolved":true,"context_lines":[{"line_number":198,"context_line":"            resp \u003d _query_server(conn)"},{"line_number":199,"context_line":"            min_ver, max_ver \u003d self._parse_version_headers(resp)"},{"line_number":200,"context_line":"        # Reset the maximum version that we permit"},{"line_number":201,"context_line":"        if min_ver is None or max_ver is None:"},{"line_number":202,"context_line":"            raise RuntimeError("},{"line_number":203,"context_line":"                _(\u0027Could not determine API version range from server; \u0027"},{"line_number":204,"context_line":"                  \u0027version headers missing from response.\u0027))"}],"source_content_type":"text/x-python","patch_set":5,"id":"06b9d849_242c4584","line":201,"updated":"2026-03-15 02:27:49.000000000","message":"We need min_ver and max_ver to be real version strings. The parser can return None if the server didn’t send the headers. This check does two things: (1) after it, the type checker knows they’re strings, and (2) if they’re missing we raise a clear error instead of crashing later with some TypeError.","commit_id":"5cc86db4336a4a1cb44bb2065ee257a8d75be8e6"},{"author":{"_account_id":36770,"name":"cid","display_name":"cid","email":"cid@gr-oss.io","username":"cidelight","status":"@gr-oss upstream: Doing good IRONIC things..."},"change_message_id":"ecc90790dfbf1a905cc361aff0e86b81a4e7d614","unresolved":true,"context_lines":[{"line_number":198,"context_line":"            resp \u003d _query_server(conn)"},{"line_number":199,"context_line":"            min_ver, max_ver \u003d self._parse_version_headers(resp)"},{"line_number":200,"context_line":"        # Reset the maximum version that we permit"},{"line_number":201,"context_line":"        if min_ver is None or max_ver is None:"},{"line_number":202,"context_line":"            raise RuntimeError("},{"line_number":203,"context_line":"                _(\u0027Could not determine API version range from server; \u0027"},{"line_number":204,"context_line":"                  \u0027version headers missing from response.\u0027))"}],"source_content_type":"text/x-python","patch_set":5,"id":"d28903f9_7055a0cd","line":201,"in_reply_to":"06b9d849_242c4584","updated":"2026-03-16 14:51:45.000000000","message":"++","commit_id":"5cc86db4336a4a1cb44bb2065ee257a8d75be8e6"},{"author":{"_account_id":10342,"name":"Jay Faulkner","display_name":"JayF","email":"jay@jvf.cc","username":"JayF","status":"youtube.com/@oss-gr / podcast.gr-oss.io"},"change_message_id":"2f7af78abd2c3b57731cbe05605a963c2cee1d20","unresolved":true,"context_lines":[{"line_number":198,"context_line":"            resp \u003d _query_server(conn)"},{"line_number":199,"context_line":"            min_ver, max_ver \u003d self._parse_version_headers(resp)"},{"line_number":200,"context_line":"        # Reset the maximum version that we permit"},{"line_number":201,"context_line":"        if min_ver is None or max_ver is None:"},{"line_number":202,"context_line":"            raise RuntimeError("},{"line_number":203,"context_line":"                _(\u0027Could not determine API version range from server; \u0027"},{"line_number":204,"context_line":"                  \u0027version headers missing from response.\u0027))"}],"source_content_type":"text/x-python","patch_set":5,"id":"f12bf4e2_49711df9","line":201,"in_reply_to":"d28903f9_7055a0cd","updated":"2026-03-18 15:37:09.000000000","message":"again, if you feel this comment is needed next time please put it in the code 😊","commit_id":"5cc86db4336a4a1cb44bb2065ee257a8d75be8e6"},{"author":{"_account_id":10342,"name":"Jay Faulkner","display_name":"JayF","email":"jay@jvf.cc","username":"JayF","status":"youtube.com/@oss-gr / podcast.gr-oss.io"},"change_message_id":"2f7af78abd2c3b57731cbe05605a963c2cee1d20","unresolved":true,"context_lines":[{"line_number":289,"context_line":"        endpoint_override \u003d getattr(self, \u0027endpoint_override\u0027, None)"},{"line_number":290,"context_line":"        host, port \u003d get_server(endpoint_override)"},{"line_number":291,"context_line":"        if host is not None and port is not None:"},{"line_number":292,"context_line":"            filecache.save_data(host\u003dhost, port\u003dport, data\u003dnegotiated_ver)"},{"line_number":293,"context_line":""},{"line_number":294,"context_line":"        return negotiated_ver"},{"line_number":295,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"2745bbd6_708cc9ac","line":292,"updated":"2026-03-18 15:37:09.000000000","message":"I\u0027ve read the code multiple times; I think this is actually a bugfix in hiding.","commit_id":"5cc86db4336a4a1cb44bb2065ee257a8d75be8e6"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"4bc66fea3b1c33d5f031a052e324d7fca14afd6b","unresolved":true,"context_lines":[{"line_number":391,"context_line":"        endpoint_filter \u003d self._get_endpoint_filter()"},{"line_number":392,"context_line":"        # type of endpoint_filter is incompatible with ksa stubs"},{"line_number":393,"context_line":"        endpoint \u003d self.get_endpoint("},{"line_number":394,"context_line":"            **endpoint_filter  # type: ignore[arg-type]"},{"line_number":395,"context_line":"        )"},{"line_number":396,"context_line":"        if endpoint is None:"},{"line_number":397,"context_line":"            raise exc.EndpointNotFound("}],"source_content_type":"text/x-python","patch_set":5,"id":"c8c7e87c_71ea30e2","line":394,"updated":"2026-03-19 11:05:08.000000000","message":"This is happening because you\u0027re passing what mypy see as an arbitrary dict (technically `dict[str, str | list[str] | None]`) when `get_endpoint` expects a specific set of kwargs.\n\nIf you inline `_get_endpoint_filter` in here (which is reasonable: it\u0027ll only add 2 lines) this error should go away. You may then get more errors about e.g. `expected \u0027str\u0027, got \u0027str | None\u0027` but those a valid (albeit low-risk) bugs.","commit_id":"5cc86db4336a4a1cb44bb2065ee257a8d75be8e6"},{"author":{"_account_id":10342,"name":"Jay Faulkner","display_name":"JayF","email":"jay@jvf.cc","username":"JayF","status":"youtube.com/@oss-gr / podcast.gr-oss.io"},"change_message_id":"2f7af78abd2c3b57731cbe05605a963c2cee1d20","unresolved":true,"context_lines":[{"line_number":473,"context_line":"            # exc.from_response expects str|None; error_json is dict[str, Any]"},{"line_number":474,"context_line":"            raise exc.from_response(  # type: ignore[call-arg]"},{"line_number":475,"context_line":"                resp,"},{"line_number":476,"context_line":"                error_json.get(\u0027error_message\u0027),  # type: ignore[arg-type]"},{"line_number":477,"context_line":"                error_json.get(\u0027debuginfo\u0027),  # type: ignore[arg-type]"},{"line_number":478,"context_line":"                method,"},{"line_number":479,"context_line":"                url,"}],"source_content_type":"text/x-python","patch_set":5,"id":"11f10ffd_ca1d0206","line":476,"updated":"2026-03-18 15:37:09.000000000","message":"Wouldn\u0027t `error_json.get(\u0027error_message\u0027, \u0027\u0027)` be sufficient to make the ignore go away? Please address this in a follow-up.","commit_id":"5cc86db4336a4a1cb44bb2065ee257a8d75be8e6"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"4bc66fea3b1c33d5f031a052e324d7fca14afd6b","unresolved":true,"context_lines":[{"line_number":473,"context_line":"            # exc.from_response expects str|None; error_json is dict[str, Any]"},{"line_number":474,"context_line":"            raise exc.from_response(  # type: ignore[call-arg]"},{"line_number":475,"context_line":"                resp,"},{"line_number":476,"context_line":"                error_json.get(\u0027error_message\u0027),  # type: ignore[arg-type]"},{"line_number":477,"context_line":"                error_json.get(\u0027debuginfo\u0027),  # type: ignore[arg-type]"},{"line_number":478,"context_line":"                method,"},{"line_number":479,"context_line":"                url,"}],"source_content_type":"text/x-python","patch_set":5,"id":"0cdabbaf_474af8fc","line":476,"in_reply_to":"11f10ffd_ca1d0206","updated":"2026-03-19 11:05:08.000000000","message":"I suspect you\u0027ll need a `cast` here. That or you could add a type assertion above, but that seems like a bad idea here in the error path.","commit_id":"5cc86db4336a4a1cb44bb2065ee257a8d75be8e6"}]}
