)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":38828,"name":"Karan Anand","display_name":"Karan","email":"anandkarancompsci@gmail.com","username":"anandkaranubc"},"change_message_id":"726a2549bdf2d592c976adea0bf8d6811d1b33cf","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"1782232c_579c1f9e","updated":"2026-03-01 00:40:54.000000000","message":"Thanks for the review again. I have updated the commit.","commit_id":"2c6a1ff6e6142debdb10082c011cfd7cd44560c4"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"04857b2a3da55d33794820a5102d5fefefdfff9b","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":1,"id":"7323c0a2_7587ff91","updated":"2026-02-28 20:07:07.000000000","message":"Too much use of Any to cheat. There’s no value in type annotations if everything is just Any.","commit_id":"2c6a1ff6e6142debdb10082c011cfd7cd44560c4"},{"author":{"_account_id":38828,"name":"Karan Anand","display_name":"Karan","email":"anandkarancompsci@gmail.com","username":"anandkaranubc"},"change_message_id":"726a2549bdf2d592c976adea0bf8d6811d1b33cf","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":1,"id":"784f38c8_0738facd","in_reply_to":"7323c0a2_7587ff91","updated":"2026-03-01 00:40:54.000000000","message":"Thanks @cardoe@cardoe.com for the review! I really appreciate you pointing that out, and I apologize for the oversight. I do try to be very careful whenever I use Any, though I agree it can sometimes be tempting to rely on it. I’ll definitely be more mindful about avoiding it where possible going forward.","commit_id":"2c6a1ff6e6142debdb10082c011cfd7cd44560c4"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"1948b8a5bfb089092dfda0e8c0fa10e2298682ad","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"3e1c6572_87475eca","updated":"2026-03-27 14:19:56.000000000","message":"A post-merge review. I think it would be good to see a follow-up addressing at least the generic comments, though I think there\u0027s good value in replacing `kwargs` building also","commit_id":"b507680903a158b2b5d73bd2b00a14ec9420456b"}],"ironicclient/common/base.py":[{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"04857b2a3da55d33794820a5102d5fefefdfff9b","unresolved":true,"context_lines":[{"line_number":29,"context_line":"from ironicclient import exc"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"def getid(obj: Any) -\u003e Any:"},{"line_number":33,"context_line":"    \"\"\"Wrapper to get  object\u0027s ID."},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    Abstracts the common pattern of allowing both an object or an"}],"source_content_type":"text/x-python","patch_set":1,"id":"5ff2e0f2_6e1e215d","line":32,"updated":"2026-02-28 20:07:07.000000000","message":"This doesn’t return an Any. It’s either a UUID or a str which should be a type itself that’s UUIDStr","commit_id":"2c6a1ff6e6142debdb10082c011cfd7cd44560c4"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"04857b2a3da55d33794820a5102d5fefefdfff9b","unresolved":true,"context_lines":[{"line_number":44,"context_line":"class Manager(object, metaclass\u003dabc.ABCMeta):"},{"line_number":45,"context_line":"    \"\"\"Provides  CRUD operations with a particular API.\"\"\""},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    def __init__(self, api: Any) -\u003e None:"},{"line_number":48,"context_line":"        self.api \u003d api"},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"    def _path(self, resource_id: str | None \u003d None) -\u003e str:"}],"source_content_type":"text/x-python","patch_set":1,"id":"c82e9b06_48be3b31","line":47,"updated":"2026-02-28 20:07:07.000000000","message":"api is not an Any. I haven’t looked at the code but I believe it’s a requests.Session","commit_id":"2c6a1ff6e6142debdb10082c011cfd7cd44560c4"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"04857b2a3da55d33794820a5102d5fefefdfff9b","unresolved":true,"context_lines":[{"line_number":179,"context_line":""},{"line_number":180,"context_line":"        if limit is not None:"},{"line_number":181,"context_line":"            limit \u003d int(limit)"},{"line_number":182,"context_line":"        kwargs: dict[str, Any] \u003d {\"headers\": {}}"},{"line_number":183,"context_line":"        if os_ironic_api_version is not None:"},{"line_number":184,"context_line":"            kwargs[\u0027headers\u0027]["},{"line_number":185,"context_line":"                \u0027X-OpenStack-Ironic-API-Version\u0027] \u003d os_ironic_api_version"}],"source_content_type":"text/x-python","patch_set":1,"id":"347981c8_3087d602","line":182,"updated":"2026-02-28 20:07:07.000000000","message":"Not an Any. Str, not or float.","commit_id":"2c6a1ff6e6142debdb10082c011cfd7cd44560c4"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"1948b8a5bfb089092dfda0e8c0fa10e2298682ad","unresolved":true,"context_lines":[{"line_number":179,"context_line":""},{"line_number":180,"context_line":"        if limit is not None:"},{"line_number":181,"context_line":"            limit \u003d int(limit)"},{"line_number":182,"context_line":"        kwargs: dict[str, Any] \u003d {\"headers\": {}}"},{"line_number":183,"context_line":"        if os_ironic_api_version is not None:"},{"line_number":184,"context_line":"            kwargs[\u0027headers\u0027]["},{"line_number":185,"context_line":"                \u0027X-OpenStack-Ironic-API-Version\u0027] \u003d os_ironic_api_version"}],"source_content_type":"text/x-python","patch_set":1,"id":"b1140ae6_dfae5483","line":182,"in_reply_to":"2cfb6f11_6a1de57e","updated":"2026-03-27 14:19:56.000000000","message":"Personally, I think it would be better to get rid of kwargs and instead create a `headers` attribute. See below.","commit_id":"2c6a1ff6e6142debdb10082c011cfd7cd44560c4"},{"author":{"_account_id":38828,"name":"Karan Anand","display_name":"Karan","email":"anandkarancompsci@gmail.com","username":"anandkaranubc"},"change_message_id":"726a2549bdf2d592c976adea0bf8d6811d1b33cf","unresolved":true,"context_lines":[{"line_number":179,"context_line":""},{"line_number":180,"context_line":"        if limit is not None:"},{"line_number":181,"context_line":"            limit \u003d int(limit)"},{"line_number":182,"context_line":"        kwargs: dict[str, Any] \u003d {\"headers\": {}}"},{"line_number":183,"context_line":"        if os_ironic_api_version is not None:"},{"line_number":184,"context_line":"            kwargs[\u0027headers\u0027]["},{"line_number":185,"context_line":"                \u0027X-OpenStack-Ironic-API-Version\u0027] \u003d os_ironic_api_version"}],"source_content_type":"text/x-python","patch_set":1,"id":"2cfb6f11_6a1de57e","line":182,"in_reply_to":"347981c8_3087d602","updated":"2026-03-01 00:40:54.000000000","message":"Thanks for the comment. The reason why I thought `kwargs` is `dict[str, Any]` because its values in, for example, `headers` is `dict[str, str]`, `body` is `list[dict[str, Any]]`, and `params` is `dict[str, Any]`. I think there isn’t a single narrower value type that cleanly covers all of them, so this felt like an appropriate use of `dict[str, Any]`. Suggestions please? Thanks!","commit_id":"2c6a1ff6e6142debdb10082c011cfd7cd44560c4"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"1948b8a5bfb089092dfda0e8c0fa10e2298682ad","unresolved":true,"context_lines":[{"line_number":44,"context_line":"        return cast(str, obj)"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"class Manager(object, metaclass\u003dabc.ABCMeta):"},{"line_number":48,"context_line":"    \"\"\"Provides  CRUD operations with a particular API.\"\"\""},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"    def __init__(self, api: SessionClient) -\u003e None:"}],"source_content_type":"text/x-python","patch_set":2,"id":"7b34b83f_7ef8602f","line":47,"updated":"2026-03-27 14:19:56.000000000","message":"If you made this a generic, you would be able to correctly type the return values of most of these functions. I have yet to test this but you want something like this.\n\n```suggestion\nResourceT \u003d TypeVar(\u0027ResourceT\u0027, bound\u003dResource)\n\n\nclass Manager(Generic[ResourceT], metaclass\u003dabc.ABCMeta):\n```","commit_id":"b507680903a158b2b5d73bd2b00a14ec9420456b"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"1948b8a5bfb089092dfda0e8c0fa10e2298682ad","unresolved":true,"context_lines":[{"line_number":61,"context_line":""},{"line_number":62,"context_line":"    @property"},{"line_number":63,"context_line":"    @abc.abstractmethod"},{"line_number":64,"context_line":"    def resource_class(self) -\u003e type[Resource]:"},{"line_number":65,"context_line":"        \"\"\"The resource class\"\"\""},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"    @property"}],"source_content_type":"text/x-python","patch_set":2,"id":"82a3e5a8_a88fdda9","line":64,"updated":"2026-03-27 14:19:56.000000000","message":"In a generic world this becomes:\n\n```suggestion\n    def resource_class(self) -\u003e type[ResourceT]:\n```","commit_id":"b507680903a158b2b5d73bd2b00a14ec9420456b"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"1948b8a5bfb089092dfda0e8c0fa10e2298682ad","unresolved":true,"context_lines":[{"line_number":75,"context_line":"        fields: list[str] | None \u003d None,"},{"line_number":76,"context_line":"        os_ironic_api_version: str | None \u003d None,"},{"line_number":77,"context_line":"        global_request_id: str | None \u003d None,"},{"line_number":78,"context_line":"    ) -\u003e Resource | None:"},{"line_number":79,"context_line":"        \"\"\"Retrieve a resource."},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"        :param resource_id: Identifier of the resource."}],"source_content_type":"text/x-python","patch_set":2,"id":"9ef1c2ea_f3feceae","line":78,"updated":"2026-03-27 14:19:56.000000000","message":"```suggestion\n    ) -\u003e ResourceT | None:\n```","commit_id":"b507680903a158b2b5d73bd2b00a14ec9420456b"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"1948b8a5bfb089092dfda0e8c0fa10e2298682ad","unresolved":true,"context_lines":[{"line_number":143,"context_line":"        else:"},{"line_number":144,"context_line":"            data \u003d body"},{"line_number":145,"context_line":""},{"line_number":146,"context_line":"        if not isinstance(data, list):"},{"line_number":147,"context_line":"            data \u003d [data]"},{"line_number":148,"context_line":""},{"line_number":149,"context_line":"        return cast(list[Any], data)"},{"line_number":150,"context_line":""},{"line_number":151,"context_line":"    def _list_pagination("},{"line_number":152,"context_line":"        self,"}],"source_content_type":"text/x-python","patch_set":2,"id":"cc3f1d49_2e8a550b","line":149,"range":{"start_line":146,"start_character":8,"end_line":149,"end_character":36},"updated":"2026-03-27 14:19:56.000000000","message":"nit: I believe you could avoid the cast by reworking this as:\n\n\n```suggestion\n        if not isinstance(data, list):\n            return [data]\n\n        return data\n```","commit_id":"b507680903a158b2b5d73bd2b00a14ec9420456b"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"1948b8a5bfb089092dfda0e8c0fa10e2298682ad","unresolved":true,"context_lines":[{"line_number":148,"context_line":""},{"line_number":149,"context_line":"        return cast(list[Any], data)"},{"line_number":150,"context_line":""},{"line_number":151,"context_line":"    def _list_pagination("},{"line_number":152,"context_line":"        self,"},{"line_number":153,"context_line":"        url: str,"},{"line_number":154,"context_line":"        response_key: str | None \u003d None,"},{"line_number":155,"context_line":"        obj_class: type[Resource] | None \u003d None,"},{"line_number":156,"context_line":"        limit: int | None \u003d None,"},{"line_number":157,"context_line":"        os_ironic_api_version: str | None \u003d None,"},{"line_number":158,"context_line":"        global_request_id: str | None \u003d None,"},{"line_number":159,"context_line":"    ) -\u003e list[Resource]:"},{"line_number":160,"context_line":"        \"\"\"Retrieve a list of items."},{"line_number":161,"context_line":""},{"line_number":162,"context_line":"        The Ironic API is configured to return a maximum number of"}],"source_content_type":"text/x-python","patch_set":2,"id":"092802e7_ab69d34d","line":159,"range":{"start_line":151,"start_character":0,"end_line":159,"end_character":24},"updated":"2026-03-27 14:19:56.000000000","message":"This one *may* be a bit trickier. Is `obj_class` expected to be a subclass of `self.resource`? If so, this would be:\n\n```suggestion\n    def _list_pagination(\n        self,\n        url: str,\n        response_key: str | None \u003d None,\n        obj_class: type[ResourceT] | None \u003d None,\n        limit: int | None \u003d None,\n        os_ironic_api_version: str | None \u003d None,\n        global_request_id: str | None \u003d None,\n    ) -\u003e list[ResourceT]:\n```\n\nIf it\u0027s *not* required to be that, you\u0027ll need two overloads: one handling `obj_class\u003dNone` and the other handling an arbitrary resource type:\n\n```\n    @overload\n    def _list_pagination(\n        self,\n        url: str,\n        response_key: str | None \u003d None,\n        obj_class: None \u003d None,\n        limit: int | None \u003d None,\n        os_ironic_api_version: str | None \u003d None,\n        global_request_id: str | None \u003d None,\n    ) -\u003e list[ResourceT]: ...\n    \n    @overload\n    def _list_pagination(\n        self,\n        url: str,\n        response_key: str | None \u003d None,\n        obj_class: type[ResourceT2] \u003d ...,\n        limit: int | None \u003d None,\n        os_ironic_api_version: str | None \u003d None,\n        global_request_id: str | None \u003d None,\n    ) -\u003e list[ResourceT2]: ...\n\n    def _list_pagination(\n        self,\n        url: str,\n        response_key: str | None \u003d None,\n        obj_class: type[ResourceT] | None \u003d None,\n        limit: int | None \u003d None,\n        os_ironic_api_version: str | None \u003d None,\n        global_request_id: str | None \u003d None,\n    ) -\u003e list[ResourceT] | list[ResourceT2]:\n```\n\nnote that you\u0027d also have to define a separate TypeVar since `ResourceT` would be bound at this point.","commit_id":"b507680903a158b2b5d73bd2b00a14ec9420456b"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"1948b8a5bfb089092dfda0e8c0fa10e2298682ad","unresolved":true,"context_lines":[{"line_number":182,"context_line":""},{"line_number":183,"context_line":"        if limit is not None:"},{"line_number":184,"context_line":"            limit \u003d int(limit)"},{"line_number":185,"context_line":"        kwargs: dict[str, Any] \u003d {\"headers\": {}}"},{"line_number":186,"context_line":"        if os_ironic_api_version is not None:"},{"line_number":187,"context_line":"            kwargs[\u0027headers\u0027]["},{"line_number":188,"context_line":"                \u0027X-OpenStack-Ironic-API-Version\u0027] \u003d os_ironic_api_version"},{"line_number":189,"context_line":"        if global_request_id is not None:"},{"line_number":190,"context_line":"            kwargs[\"headers\"][\"X-Openstack-Request-Id\"] \u003d global_request_id"},{"line_number":191,"context_line":""},{"line_number":192,"context_line":"        # NOTE(jroll)"},{"line_number":193,"context_line":"        # endpoint_trimmed is what is prepended if we only pass a path"}],"source_content_type":"text/x-python","patch_set":2,"id":"a8c62494_dd85d89d","line":190,"range":{"start_line":185,"start_character":0,"end_line":190,"end_character":75},"updated":"2026-03-27 14:19:56.000000000","message":"```suggestion\n        headers: dict[str, str | int] \u003d {}\n        if os_ironic_api_version is not None:\n            headers[\u0027X-OpenStack-Ironic-API-Version\u0027] \u003d os_ironic_api_version\n        if global_request_id is not None:\n            headers[\"X-Openstack-Request-Id\"] \u003d global_request_id\n```\n\nThis would have the advantage of allowing the type stubs to detect if we\u0027re passing invalid values for headers.","commit_id":"b507680903a158b2b5d73bd2b00a14ec9420456b"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"1948b8a5bfb089092dfda0e8c0fa10e2298682ad","unresolved":true,"context_lines":[{"line_number":259,"context_line":""},{"line_number":260,"context_line":"        data \u003d self._format_body_data(json_body, response_key)"},{"line_number":261,"context_line":"        return data"},{"line_number":262,"context_line":""},{"line_number":263,"context_line":"    def _list("},{"line_number":264,"context_line":"        self,"},{"line_number":265,"context_line":"        url: str,"},{"line_number":266,"context_line":"        response_key: str | None \u003d None,"},{"line_number":267,"context_line":"        obj_class: type[Resource] | None \u003d None,"},{"line_number":268,"context_line":"        body: dict[str, Any] | None \u003d None,"},{"line_number":269,"context_line":"        os_ironic_api_version: str | None \u003d None,"},{"line_number":270,"context_line":"        global_request_id: str | None \u003d None,"},{"line_number":271,"context_line":"    ) -\u003e list[Resource]:"},{"line_number":272,"context_line":"        if obj_class is None:"},{"line_number":273,"context_line":"            obj_class \u003d self.resource_class"},{"line_number":274,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"b8a27472_75dd9523","line":271,"range":{"start_line":262,"start_character":1,"end_line":271,"end_character":24},"updated":"2026-03-27 14:19:56.000000000","message":"As above, this should either use `s/Resource/ResourceT/` if we require subclasses of self.resource_type for `obj_class` else we should define some overloads.","commit_id":"b507680903a158b2b5d73bd2b00a14ec9420456b"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"1948b8a5bfb089092dfda0e8c0fa10e2298682ad","unresolved":true,"context_lines":[{"line_number":307,"context_line":"        os_ironic_api_version: str | None \u003d None,"},{"line_number":308,"context_line":"        global_request_id: str | None \u003d None,"},{"line_number":309,"context_line":"        params: dict[str, Any] | None \u003d None,"},{"line_number":310,"context_line":"    ) -\u003e Resource | None:"},{"line_number":311,"context_line":"        \"\"\"Update a resource."},{"line_number":312,"context_line":""},{"line_number":313,"context_line":"        :param resource_id: Resource identifier."}],"source_content_type":"text/x-python","patch_set":2,"id":"a421f1ff_3d54c478","line":310,"updated":"2026-03-27 14:19:56.000000000","message":"```suggestion\n    ) -\u003e ResourceT | None:\n```","commit_id":"b507680903a158b2b5d73bd2b00a14ec9420456b"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"1948b8a5bfb089092dfda0e8c0fa10e2298682ad","unresolved":true,"context_lines":[{"line_number":320,"context_line":"        :param params: query parameters to pass."},{"line_number":321,"context_line":"        \"\"\""},{"line_number":322,"context_line":""},{"line_number":323,"context_line":"        url \u003d self._path(resource_id)"},{"line_number":324,"context_line":"        kwargs: dict[str, Any] \u003d {\"headers\": {}}"},{"line_number":325,"context_line":"        if patch is not None:"},{"line_number":326,"context_line":"            kwargs[\u0027body\u0027] \u003d patch"},{"line_number":327,"context_line":"        if os_ironic_api_version is not None:"},{"line_number":328,"context_line":"            kwargs[\u0027headers\u0027]["},{"line_number":329,"context_line":"                \u0027X-OpenStack-Ironic-API-Version\u0027] \u003d os_ironic_api_version"},{"line_number":330,"context_line":"        if global_request_id is not None:"},{"line_number":331,"context_line":"            kwargs[\"headers\"][\"X-Openstack-Request-Id\"] \u003d global_request_id"},{"line_number":332,"context_line":"        if params:"},{"line_number":333,"context_line":"            kwargs[\u0027params\u0027] \u003d params"},{"line_number":334,"context_line":"        _resp, body \u003d self.api.json_request(method, url, **kwargs)"},{"line_number":335,"context_line":"        # PATCH/PUT requests may not return a body"},{"line_number":336,"context_line":"        if body:"}],"source_content_type":"text/x-python","patch_set":2,"id":"10eff8e9_22b993ab","line":333,"range":{"start_line":323,"start_character":37,"end_line":333,"end_character":37},"updated":"2026-03-27 14:19:56.000000000","message":"As above, I believe it would be better to build `headers`, `body` and `params` separately so that we always pass them. I believe requests won\u0027t complain if any of these are `None`.","commit_id":"b507680903a158b2b5d73bd2b00a14ec9420456b"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"1948b8a5bfb089092dfda0e8c0fa10e2298682ad","unresolved":true,"context_lines":[{"line_number":360,"context_line":"                             headers\u003dheaders)"},{"line_number":361,"context_line":""},{"line_number":362,"context_line":""},{"line_number":363,"context_line":"class CreateManager(Manager, metaclass\u003dabc.ABCMeta):"},{"line_number":364,"context_line":"    \"\"\"Provides creation operations with a particular API.\"\"\""},{"line_number":365,"context_line":""},{"line_number":366,"context_line":"    @property"}],"source_content_type":"text/x-python","patch_set":2,"id":"df084477_55e44976","line":363,"updated":"2026-03-27 14:19:56.000000000","message":"I think this inherits the superclasses genericness so you can just do:\n\n```suggestion\nclass CreateManager(Manager[ResourceT], metaclass\u003dabc.ABCMeta):\n```","commit_id":"b507680903a158b2b5d73bd2b00a14ec9420456b"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"1948b8a5bfb089092dfda0e8c0fa10e2298682ad","unresolved":true,"context_lines":[{"line_number":373,"context_line":"        os_ironic_api_version: str | None \u003d None,"},{"line_number":374,"context_line":"        global_request_id: str | None \u003d None,"},{"line_number":375,"context_line":"        **kwargs: Any,"},{"line_number":376,"context_line":"    ) -\u003e Resource | None:"},{"line_number":377,"context_line":"        \"\"\"Create a resource based on a kwargs dictionary of attributes."},{"line_number":378,"context_line":""},{"line_number":379,"context_line":"        :param kwargs: A dictionary containing the attributes of the resource"}],"source_content_type":"text/x-python","patch_set":2,"id":"d5aa00ea_8790ee5b","line":376,"updated":"2026-03-27 14:19:56.000000000","message":"```suggestion\n    ) -\u003e ResourceT | None:\n```","commit_id":"b507680903a158b2b5d73bd2b00a14ec9420456b"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"1948b8a5bfb089092dfda0e8c0fa10e2298682ad","unresolved":true,"context_lines":[{"line_number":409,"context_line":"            \u0027POST\u0027, url, body\u003dnew, headers\u003dheaders,"},{"line_number":410,"context_line":"        )"},{"line_number":411,"context_line":"        if body:"},{"line_number":412,"context_line":"            return self.resource_class(self, body)  # type: ignore[arg-type]"},{"line_number":413,"context_line":"        return None"},{"line_number":414,"context_line":""},{"line_number":415,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"2b2db846_2f48b777","line":412,"updated":"2026-03-27 14:19:56.000000000","message":"I think this will go away if you make the generic changes.","commit_id":"b507680903a158b2b5d73bd2b00a14ec9420456b"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"1948b8a5bfb089092dfda0e8c0fa10e2298682ad","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":2,"id":"5b917432_d0f33c83","line":424,"range":{"start_line":416,"start_character":0,"end_line":424,"end_character":1},"updated":"2026-03-27 14:19:56.000000000","message":"Consider moving this to the top of the file (before `Manager`) to avoid forward references. This might let you drop `__future__.annotations` also.","commit_id":"b507680903a158b2b5d73bd2b00a14ec9420456b"}]}
