We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Usage of assert
These assert values should be added or updated with a message to explain what went wrong. 

- [ ] praw/objector.py: Line 40 has phrase assert, please edit and remove this.
- [ ] praw/objector.py: Line 171 has phrase assert, please edit and remove this.
- [x] praw/models/comment_forest.py: Line 82 has phrase assert, please edit and remove this.
- [x] praw/models/trophy.py: Line 45 has phrase assert, please edit and remove this.
- [x] praw/models/reddit/redditor.py: Line 141 has phrase assert, please edit and remove this.
- [x] praw/models/reddit/widgets.py: Line 1403 has phrase assert, please edit and remove this.
- [x] praw/models/reddit/subreddit.py: Line 2774 has phrase assert, please edit and remove this.
- [ ] praw/models/reddit/more.py: Line 48 has phrase assert, please edit and remove this.
- [ ] praw/models/reddit/more.py: Line 67 has phrase assert, please edit and remove this.
- [ ] praw/models/reddit/more.py: Line 75 has phrase assert, please edit and remove this.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `praw/objector.py`
Content:
```
1 """Provides the Objector class."""
2 
3 from typing import Any, Dict, List, Optional, TypeVar, Union
4 
5 from .exceptions import APIException, ClientException
6 from .models.reddit.base import RedditBase
7 from .util import snake_case_keys
8 
9 Reddit = TypeVar("Reddit")
10 
11 
12 class Objector:
13     """The objector builds :class:`.RedditBase` objects."""
14 
15     @classmethod
16     def parse_error(
17         cls, data: Union[List[Any], Dict[str, Dict[str, str]]]
18     ) -> Optional[APIException]:
19         """Convert JSON response into an error object.
20 
21         :param data: The dict to be converted.
22         :returns: An instance of :class:`~.APIException`, or ``None`` if
23             ``data`` doesn't fit this model.
24 
25         """
26         if isinstance(data, list):
27             # Fetching a Submission returns a list (of two items).
28             # Although it's handled manually in `Submission._fetch()`,
29             # assume it's a possibility here.
30             return None
31 
32         errors = data.get("json", {}).get("errors")
33         if errors is None:
34             return None
35         if len(errors) < 1:
36             # See `Collection._fetch()`.
37             raise ClientException("successful error response", data)
38         if len(errors) > 1:
39             # Yet to be observed.
40             raise AssertionError(
41                 "multiple error descriptions in response", data
42             )
43 
44         return APIException(*errors[0])
45 
46     @classmethod
47     def check_error(cls, data: Union[List[Any], Dict[str, Dict[str, str]]]):
48         """Raise an error if the argument resolves to an error object."""
49         error = cls.parse_error(data)
50         if error:
51             raise error
52 
53     def __init__(
54         self, reddit: Reddit, parsers: Optional[Dict[str, Any]] = None
55     ):
56         """Initialize an Objector instance.
57 
58         :param reddit: An instance of :class:`~.Reddit`.
59 
60         """
61         self.parsers = {} if parsers is None else parsers
62         self._reddit = reddit
63 
64     def _objectify_dict(self, data):
65         """Create RedditBase objects from dicts.
66 
67         :param data: The structured data, assumed to be a dict.
68         :returns: An instance of :class:`~.RedditBase`.
69 
70         """
71         if {"conversation", "messages", "modActions"}.issubset(data):
72             parser = self.parsers["ModmailConversation"]
73         elif {"actionTypeId", "author", "date"}.issubset(data):
74             # Modmail mod action
75             data = snake_case_keys(data)
76             parser = self.parsers["ModmailAction"]
77         elif {"bodyMarkdown", "isInternal"}.issubset(data):
78             # Modmail message
79             data = snake_case_keys(data)
80             parser = self.parsers["ModmailMessage"]
81         elif {"isAdmin", "isDeleted"}.issubset(data):
82             # Modmail author
83             data = snake_case_keys(data)
84             # Prevent clobbering base-36 id
85             del data["id"]
86             data["is_subreddit_mod"] = data.pop("is_mod")
87             parser = self.parsers[self._reddit.config.kinds["redditor"]]
88         elif {"banStatus", "muteStatus", "recentComments"}.issubset(data):
89             # Modmail user
90             data = snake_case_keys(data)
91             data["created_string"] = data.pop("created")
92             parser = self.parsers[self._reddit.config.kinds["redditor"]]
93         elif {"displayName", "id", "type"}.issubset(data):
94             # Modmail subreddit
95             data = snake_case_keys(data)
96             parser = self.parsers[self._reddit.config.kinds[data["type"]]]
97         elif {"date", "id", "name"}.issubset(data) or {
98             "id",
99             "name",
100             "permissions",
101         }.issubset(data):
102             parser = self.parsers[self._reddit.config.kinds["redditor"]]
103         elif {"text", "url"}.issubset(data):
104             if "color" in data or "linkUrl" in data:
105                 parser = self.parsers["Button"]
106             else:
107                 parser = self.parsers["MenuLink"]
108         elif {"children", "text"}.issubset(data):
109             parser = self.parsers["Submenu"]
110         elif {"height", "url", "width"}.issubset(data):
111             parser = self.parsers["Image"]
112         elif {"isSubscribed", "name", "subscribers"}.issubset(data):
113             # discards icon and subscribed information
114             return self._reddit.subreddit(data["name"])
115         elif {"authorFlairType", "name"}.issubset(data):
116             # discards flair information
117             return self._reddit.redditor(data["name"])
118         elif {"parent_id"}.issubset(data):
119             parser = self.parsers[self._reddit.config.kinds["comment"]]
120         elif "collection_id" in data.keys():
121             parser = self.parsers["Collection"]
122         else:
123             if "user" in data:
124                 parser = self.parsers[self._reddit.config.kinds["redditor"]]
125                 data["user"] = parser.parse(
126                     {"name": data["user"]}, self._reddit
127                 )
128             return data
129         return parser.parse(data, self._reddit)
130 
131     def objectify(
132         self, data: Optional[Union[Dict[str, Any], List[Any]]]
133     ) -> Optional[Union[RedditBase, Dict[str, Any], List[Any]]]:
134         """Create RedditBase objects from data.
135 
136         :param data: The structured data.
137         :returns: An instance of :class:`~.RedditBase`, or ``None`` if
138             given ``data`` is ``None``.
139 
140         """
141         # pylint: disable=too-many-return-statements
142         if data is None:  # 204 no content
143             return None
144         if isinstance(data, list):
145             return [self.objectify(item) for item in data]
146         if "kind" in data and (
147             "shortName" in data or data["kind"] in ("menu", "moderators")
148         ):
149             # This is a widget
150             parser = self.parsers.get(data["kind"], self.parsers["widget"])
151             return parser.parse(data, self._reddit)
152         if {"kind", "data"}.issubset(data) and data["kind"] in self.parsers:
153             parser = self.parsers[data["kind"]]
154             return parser.parse(data["data"], self._reddit)
155         if "json" in data and "data" in data["json"]:
156             if "websocket_url" in data["json"]["data"]:
157                 return data
158             if "things" in data["json"]["data"]:  # Submission.reply
159                 return self.objectify(data["json"]["data"]["things"])
160             if "url" in data["json"]["data"]:  # Subreddit.submit
161                 # The URL is the URL to the submission, so it's removed.
162                 del data["json"]["data"]["url"]
163                 parser = self.parsers[self._reddit.config.kinds["submission"]]
164             else:
165                 parser = self.parsers["LiveUpdateEvent"]
166             return parser.parse(data["json"]["data"], self._reddit)
167         if "json" in data and "errors" in data["json"]:
168             errors = data["json"]["errors"]
169             if len(errors) == 1:
170                 raise APIException(*errors[0])
171             assert not errors
172         elif isinstance(data, dict):
173             return self._objectify_dict(data)
174 
175         return data
176
```

Path: `praw/models/reddit/more.py`
Content:
```
1 """Provide the MoreComments class."""
2 from typing import Any, Dict, List, TypeVar, Union
3 
4 from ...const import API_PATH
5 from ..base import PRAWBase
6 
7 _MoreComments = TypeVar("_MoreComments")
8 Comment = TypeVar("Comment")
9 Reddit = TypeVar("Reddit")
10 
11 
12 class MoreComments(PRAWBase):
13     """A class indicating there are more comments."""
14 
15     def __init__(self, reddit: Reddit, _data: Dict[str, Any]):
16         """Construct an instance of the MoreComments object."""
17         self.count = self.parent_id = None
18         self.children = []
19         super().__init__(reddit, _data=_data)
20         self._comments = None
21         self.submission = None
22 
23     def __eq__(self, other: Union[str, _MoreComments]) -> bool:
24         """Return True if these MoreComments instances are the same."""
25         return (
26             isinstance(other, self.__class__)
27             and self.count == other.count
28             and self.children == other.children
29         )
30 
31     def __lt__(self, other: _MoreComments) -> bool:
32         """Provide a sort order on the MoreComments object."""
33         # To work with heapq a "smaller" item is the one with the most comments
34         # We are intentionally making the biggest element the smallest element
35         # to turn the min-heap implementation in heapq into a max-heap.
36         return self.count > other.count
37 
38     def __repr__(self) -> str:
39         """Return a string representation of the MoreComments instance."""
40         children = self.children[:4]
41         if len(self.children) > 4:
42             children[-1] = "..."
43         return "<{} count={}, children={!r}>".format(
44             self.__class__.__name__, self.count, children
45         )
46 
47     def _continue_comments(self, update):
48         assert not self.children
49         parent = self._load_comment(self.parent_id.split("_", 1)[1])
50         self._comments = parent.replies
51         if update:
52             for comment in self._comments:
53                 comment.submission = self.submission
54         return self._comments
55 
56     def _load_comment(self, comment_id):
57         path = "{}_/{}".format(
58             API_PATH["submission"].format(id=self.submission.id), comment_id
59         )
60         _, comments = self._reddit.get(
61             path,
62             params={
63                 "limit": self.submission.comment_limit,
64                 "sort": self.submission.comment_sort,
65             },
66         )
67         assert len(comments.children) == 1
68         return comments.children[0]
69 
70     def comments(self, update: bool = True) -> List[Comment]:
71         """Fetch and return the comments for a single MoreComments object."""
72         if self._comments is None:
73             if self.count == 0:  # Handle 'continue this thread'
74                 return self._continue_comments(update)
75             assert self.children
76             data = {
77                 "children": ",".join(self.children),
78                 "link_id": self.submission.fullname,
79                 "sort": self.submission.comment_sort,
80             }
81             self._comments = self._reddit.post(
82                 API_PATH["morechildren"], data=data
83             )
84             if update:
85                 for comment in self._comments:
86                     comment.submission = self.submission
87         return self._comments
88
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/praw/models/reddit/more.py b/praw/models/reddit/more.py
--- a/praw/models/reddit/more.py
+++ b/praw/models/reddit/more.py
@@ -45,7 +45,7 @@
         )
 
     def _continue_comments(self, update):
-        assert not self.children
+        assert not self.children, "Please file a bug report with PRAW."
         parent = self._load_comment(self.parent_id.split("_", 1)[1])
         self._comments = parent.replies
         if update:
@@ -64,7 +64,9 @@
                 "sort": self.submission.comment_sort,
             },
         )
-        assert len(comments.children) == 1
+        assert (
+            len(comments.children) == 1
+        ), "Please file a bug report with PRAW."
         return comments.children[0]
 
     def comments(self, update: bool = True) -> List[Comment]:
@@ -72,7 +74,7 @@
         if self._comments is None:
             if self.count == 0:  # Handle 'continue this thread'
                 return self._continue_comments(update)
-            assert self.children
+            assert self.children, "Please file a bug report with PRAW."
             data = {
                 "children": ",".join(self.children),
                 "link_id": self.submission.fullname,
diff --git a/praw/objector.py b/praw/objector.py
--- a/praw/objector.py
+++ b/praw/objector.py
@@ -35,11 +35,10 @@
         if len(errors) < 1:
             # See `Collection._fetch()`.
             raise ClientException("successful error response", data)
-        if len(errors) > 1:
-            # Yet to be observed.
-            raise AssertionError(
-                "multiple error descriptions in response", data
-            )
+        assert not len(errors) > 1, (  # Yet to be observed.
+            "multiple error descriptions in response",
+            data,
+        )
 
         return APIException(*errors[0])
 
@@ -168,7 +167,10 @@
             errors = data["json"]["errors"]
             if len(errors) == 1:
                 raise APIException(*errors[0])
-            assert not errors
+            assert not errors, (
+                "Errors did not get raised as an APIException",
+                errors,
+            )
         elif isinstance(data, dict):
             return self._objectify_dict(data)

{"golden_diff": "diff --git a/praw/models/reddit/more.py b/praw/models/reddit/more.py\n--- a/praw/models/reddit/more.py\n+++ b/praw/models/reddit/more.py\n@@ -45,7 +45,7 @@\n         )\n \n     def _continue_comments(self, update):\n-        assert not self.children\n+        assert not self.children, \"Please file a bug report with PRAW.\"\n         parent = self._load_comment(self.parent_id.split(\"_\", 1)[1])\n         self._comments = parent.replies\n         if update:\n@@ -64,7 +64,9 @@\n                 \"sort\": self.submission.comment_sort,\n             },\n         )\n-        assert len(comments.children) == 1\n+        assert (\n+            len(comments.children) == 1\n+        ), \"Please file a bug report with PRAW.\"\n         return comments.children[0]\n \n     def comments(self, update: bool = True) -> List[Comment]:\n@@ -72,7 +74,7 @@\n         if self._comments is None:\n             if self.count == 0:  # Handle 'continue this thread'\n                 return self._continue_comments(update)\n-            assert self.children\n+            assert self.children, \"Please file a bug report with PRAW.\"\n             data = {\n                 \"children\": \",\".join(self.children),\n                 \"link_id\": self.submission.fullname,\ndiff --git a/praw/objector.py b/praw/objector.py\n--- a/praw/objector.py\n+++ b/praw/objector.py\n@@ -35,11 +35,10 @@\n         if len(errors) < 1:\n             # See `Collection._fetch()`.\n             raise ClientException(\"successful error response\", data)\n-        if len(errors) > 1:\n-            # Yet to be observed.\n-            raise AssertionError(\n-                \"multiple error descriptions in response\", data\n-            )\n+        assert not len(errors) > 1, (  # Yet to be observed.\n+            \"multiple error descriptions in response\",\n+            data,\n+        )\n \n         return APIException(*errors[0])\n \n@@ -168,7 +167,10 @@\n             errors = data[\"json\"][\"errors\"]\n             if len(errors) == 1:\n                 raise APIException(*errors[0])\n-            assert not errors\n+            assert not errors, (\n+                \"Errors did not get raised as an APIException\",\n+                errors,\n+            )\n         elif isinstance(data, dict):\n             return self._objectify_dict(data)\n", "issue": "Usage of assert\nThese assert values should be added or updated with a message to explain what went wrong. \r\n\r\n- [ ] praw/objector.py: Line 40 has phrase assert, please edit and remove this.\r\n- [ ] praw/objector.py: Line 171 has phrase assert, please edit and remove this.\r\n- [x] praw/models/comment_forest.py: Line 82 has phrase assert, please edit and remove this.\r\n- [x] praw/models/trophy.py: Line 45 has phrase assert, please edit and remove this.\r\n- [x] praw/models/reddit/redditor.py: Line 141 has phrase assert, please edit and remove this.\r\n- [x] praw/models/reddit/widgets.py: Line 1403 has phrase assert, please edit and remove this.\r\n- [x] praw/models/reddit/subreddit.py: Line 2774 has phrase assert, please edit and remove this.\r\n- [ ] praw/models/reddit/more.py: Line 48 has phrase assert, please edit and remove this.\r\n- [ ] praw/models/reddit/more.py: Line 67 has phrase assert, please edit and remove this.\r\n- [ ] praw/models/reddit/more.py: Line 75 has phrase assert, please edit and remove this.\r\n\n", "before_files": [{"content": "\"\"\"Provides the Objector class.\"\"\"\n\nfrom typing import Any, Dict, List, Optional, TypeVar, Union\n\nfrom .exceptions import APIException, ClientException\nfrom .models.reddit.base import RedditBase\nfrom .util import snake_case_keys\n\nReddit = TypeVar(\"Reddit\")\n\n\nclass Objector:\n    \"\"\"The objector builds :class:`.RedditBase` objects.\"\"\"\n\n    @classmethod\n    def parse_error(\n        cls, data: Union[List[Any], Dict[str, Dict[str, str]]]\n    ) -> Optional[APIException]:\n        \"\"\"Convert JSON response into an error object.\n\n        :param data: The dict to be converted.\n        :returns: An instance of :class:`~.APIException`, or ``None`` if\n            ``data`` doesn't fit this model.\n\n        \"\"\"\n        if isinstance(data, list):\n            # Fetching a Submission returns a list (of two items).\n            # Although it's handled manually in `Submission._fetch()`,\n            # assume it's a possibility here.\n            return None\n\n        errors = data.get(\"json\", {}).get(\"errors\")\n        if errors is None:\n            return None\n        if len(errors) < 1:\n            # See `Collection._fetch()`.\n            raise ClientException(\"successful error response\", data)\n        if len(errors) > 1:\n            # Yet to be observed.\n            raise AssertionError(\n                \"multiple error descriptions in response\", data\n            )\n\n        return APIException(*errors[0])\n\n    @classmethod\n    def check_error(cls, data: Union[List[Any], Dict[str, Dict[str, str]]]):\n        \"\"\"Raise an error if the argument resolves to an error object.\"\"\"\n        error = cls.parse_error(data)\n        if error:\n            raise error\n\n    def __init__(\n        self, reddit: Reddit, parsers: Optional[Dict[str, Any]] = None\n    ):\n        \"\"\"Initialize an Objector instance.\n\n        :param reddit: An instance of :class:`~.Reddit`.\n\n        \"\"\"\n        self.parsers = {} if parsers is None else parsers\n        self._reddit = reddit\n\n    def _objectify_dict(self, data):\n        \"\"\"Create RedditBase objects from dicts.\n\n        :param data: The structured data, assumed to be a dict.\n        :returns: An instance of :class:`~.RedditBase`.\n\n        \"\"\"\n        if {\"conversation\", \"messages\", \"modActions\"}.issubset(data):\n            parser = self.parsers[\"ModmailConversation\"]\n        elif {\"actionTypeId\", \"author\", \"date\"}.issubset(data):\n            # Modmail mod action\n            data = snake_case_keys(data)\n            parser = self.parsers[\"ModmailAction\"]\n        elif {\"bodyMarkdown\", \"isInternal\"}.issubset(data):\n            # Modmail message\n            data = snake_case_keys(data)\n            parser = self.parsers[\"ModmailMessage\"]\n        elif {\"isAdmin\", \"isDeleted\"}.issubset(data):\n            # Modmail author\n            data = snake_case_keys(data)\n            # Prevent clobbering base-36 id\n            del data[\"id\"]\n            data[\"is_subreddit_mod\"] = data.pop(\"is_mod\")\n            parser = self.parsers[self._reddit.config.kinds[\"redditor\"]]\n        elif {\"banStatus\", \"muteStatus\", \"recentComments\"}.issubset(data):\n            # Modmail user\n            data = snake_case_keys(data)\n            data[\"created_string\"] = data.pop(\"created\")\n            parser = self.parsers[self._reddit.config.kinds[\"redditor\"]]\n        elif {\"displayName\", \"id\", \"type\"}.issubset(data):\n            # Modmail subreddit\n            data = snake_case_keys(data)\n            parser = self.parsers[self._reddit.config.kinds[data[\"type\"]]]\n        elif {\"date\", \"id\", \"name\"}.issubset(data) or {\n            \"id\",\n            \"name\",\n            \"permissions\",\n        }.issubset(data):\n            parser = self.parsers[self._reddit.config.kinds[\"redditor\"]]\n        elif {\"text\", \"url\"}.issubset(data):\n            if \"color\" in data or \"linkUrl\" in data:\n                parser = self.parsers[\"Button\"]\n            else:\n                parser = self.parsers[\"MenuLink\"]\n        elif {\"children\", \"text\"}.issubset(data):\n            parser = self.parsers[\"Submenu\"]\n        elif {\"height\", \"url\", \"width\"}.issubset(data):\n            parser = self.parsers[\"Image\"]\n        elif {\"isSubscribed\", \"name\", \"subscribers\"}.issubset(data):\n            # discards icon and subscribed information\n            return self._reddit.subreddit(data[\"name\"])\n        elif {\"authorFlairType\", \"name\"}.issubset(data):\n            # discards flair information\n            return self._reddit.redditor(data[\"name\"])\n        elif {\"parent_id\"}.issubset(data):\n            parser = self.parsers[self._reddit.config.kinds[\"comment\"]]\n        elif \"collection_id\" in data.keys():\n            parser = self.parsers[\"Collection\"]\n        else:\n            if \"user\" in data:\n                parser = self.parsers[self._reddit.config.kinds[\"redditor\"]]\n                data[\"user\"] = parser.parse(\n                    {\"name\": data[\"user\"]}, self._reddit\n                )\n            return data\n        return parser.parse(data, self._reddit)\n\n    def objectify(\n        self, data: Optional[Union[Dict[str, Any], List[Any]]]\n    ) -> Optional[Union[RedditBase, Dict[str, Any], List[Any]]]:\n        \"\"\"Create RedditBase objects from data.\n\n        :param data: The structured data.\n        :returns: An instance of :class:`~.RedditBase`, or ``None`` if\n            given ``data`` is ``None``.\n\n        \"\"\"\n        # pylint: disable=too-many-return-statements\n        if data is None:  # 204 no content\n            return None\n        if isinstance(data, list):\n            return [self.objectify(item) for item in data]\n        if \"kind\" in data and (\n            \"shortName\" in data or data[\"kind\"] in (\"menu\", \"moderators\")\n        ):\n            # This is a widget\n            parser = self.parsers.get(data[\"kind\"], self.parsers[\"widget\"])\n            return parser.parse(data, self._reddit)\n        if {\"kind\", \"data\"}.issubset(data) and data[\"kind\"] in self.parsers:\n            parser = self.parsers[data[\"kind\"]]\n            return parser.parse(data[\"data\"], self._reddit)\n        if \"json\" in data and \"data\" in data[\"json\"]:\n            if \"websocket_url\" in data[\"json\"][\"data\"]:\n                return data\n            if \"things\" in data[\"json\"][\"data\"]:  # Submission.reply\n                return self.objectify(data[\"json\"][\"data\"][\"things\"])\n            if \"url\" in data[\"json\"][\"data\"]:  # Subreddit.submit\n                # The URL is the URL to the submission, so it's removed.\n                del data[\"json\"][\"data\"][\"url\"]\n                parser = self.parsers[self._reddit.config.kinds[\"submission\"]]\n            else:\n                parser = self.parsers[\"LiveUpdateEvent\"]\n            return parser.parse(data[\"json\"][\"data\"], self._reddit)\n        if \"json\" in data and \"errors\" in data[\"json\"]:\n            errors = data[\"json\"][\"errors\"]\n            if len(errors) == 1:\n                raise APIException(*errors[0])\n            assert not errors\n        elif isinstance(data, dict):\n            return self._objectify_dict(data)\n\n        return data\n", "path": "praw/objector.py"}, {"content": "\"\"\"Provide the MoreComments class.\"\"\"\nfrom typing import Any, Dict, List, TypeVar, Union\n\nfrom ...const import API_PATH\nfrom ..base import PRAWBase\n\n_MoreComments = TypeVar(\"_MoreComments\")\nComment = TypeVar(\"Comment\")\nReddit = TypeVar(\"Reddit\")\n\n\nclass MoreComments(PRAWBase):\n    \"\"\"A class indicating there are more comments.\"\"\"\n\n    def __init__(self, reddit: Reddit, _data: Dict[str, Any]):\n        \"\"\"Construct an instance of the MoreComments object.\"\"\"\n        self.count = self.parent_id = None\n        self.children = []\n        super().__init__(reddit, _data=_data)\n        self._comments = None\n        self.submission = None\n\n    def __eq__(self, other: Union[str, _MoreComments]) -> bool:\n        \"\"\"Return True if these MoreComments instances are the same.\"\"\"\n        return (\n            isinstance(other, self.__class__)\n            and self.count == other.count\n            and self.children == other.children\n        )\n\n    def __lt__(self, other: _MoreComments) -> bool:\n        \"\"\"Provide a sort order on the MoreComments object.\"\"\"\n        # To work with heapq a \"smaller\" item is the one with the most comments\n        # We are intentionally making the biggest element the smallest element\n        # to turn the min-heap implementation in heapq into a max-heap.\n        return self.count > other.count\n\n    def __repr__(self) -> str:\n        \"\"\"Return a string representation of the MoreComments instance.\"\"\"\n        children = self.children[:4]\n        if len(self.children) > 4:\n            children[-1] = \"...\"\n        return \"<{} count={}, children={!r}>\".format(\n            self.__class__.__name__, self.count, children\n        )\n\n    def _continue_comments(self, update):\n        assert not self.children\n        parent = self._load_comment(self.parent_id.split(\"_\", 1)[1])\n        self._comments = parent.replies\n        if update:\n            for comment in self._comments:\n                comment.submission = self.submission\n        return self._comments\n\n    def _load_comment(self, comment_id):\n        path = \"{}_/{}\".format(\n            API_PATH[\"submission\"].format(id=self.submission.id), comment_id\n        )\n        _, comments = self._reddit.get(\n            path,\n            params={\n                \"limit\": self.submission.comment_limit,\n                \"sort\": self.submission.comment_sort,\n            },\n        )\n        assert len(comments.children) == 1\n        return comments.children[0]\n\n    def comments(self, update: bool = True) -> List[Comment]:\n        \"\"\"Fetch and return the comments for a single MoreComments object.\"\"\"\n        if self._comments is None:\n            if self.count == 0:  # Handle 'continue this thread'\n                return self._continue_comments(update)\n            assert self.children\n            data = {\n                \"children\": \",\".join(self.children),\n                \"link_id\": self.submission.fullname,\n                \"sort\": self.submission.comment_sort,\n            }\n            self._comments = self._reddit.post(\n                API_PATH[\"morechildren\"], data=data\n            )\n            if update:\n                for comment in self._comments:\n                    comment.submission = self.submission\n        return self._comments\n", "path": "praw/models/reddit/more.py"}], "after_files": [{"content": "\"\"\"Provides the Objector class.\"\"\"\n\nfrom typing import Any, Dict, List, Optional, TypeVar, Union\n\nfrom .exceptions import APIException, ClientException\nfrom .models.reddit.base import RedditBase\nfrom .util import snake_case_keys\n\nReddit = TypeVar(\"Reddit\")\n\n\nclass Objector:\n    \"\"\"The objector builds :class:`.RedditBase` objects.\"\"\"\n\n    @classmethod\n    def parse_error(\n        cls, data: Union[List[Any], Dict[str, Dict[str, str]]]\n    ) -> Optional[APIException]:\n        \"\"\"Convert JSON response into an error object.\n\n        :param data: The dict to be converted.\n        :returns: An instance of :class:`~.APIException`, or ``None`` if\n            ``data`` doesn't fit this model.\n\n        \"\"\"\n        if isinstance(data, list):\n            # Fetching a Submission returns a list (of two items).\n            # Although it's handled manually in `Submission._fetch()`,\n            # assume it's a possibility here.\n            return None\n\n        errors = data.get(\"json\", {}).get(\"errors\")\n        if errors is None:\n            return None\n        if len(errors) < 1:\n            # See `Collection._fetch()`.\n            raise ClientException(\"successful error response\", data)\n        assert not len(errors) > 1, (  # Yet to be observed.\n            \"multiple error descriptions in response\",\n            data,\n        )\n\n        return APIException(*errors[0])\n\n    @classmethod\n    def check_error(cls, data: Union[List[Any], Dict[str, Dict[str, str]]]):\n        \"\"\"Raise an error if the argument resolves to an error object.\"\"\"\n        error = cls.parse_error(data)\n        if error:\n            raise error\n\n    def __init__(\n        self, reddit: Reddit, parsers: Optional[Dict[str, Any]] = None\n    ):\n        \"\"\"Initialize an Objector instance.\n\n        :param reddit: An instance of :class:`~.Reddit`.\n\n        \"\"\"\n        self.parsers = {} if parsers is None else parsers\n        self._reddit = reddit\n\n    def _objectify_dict(self, data):\n        \"\"\"Create RedditBase objects from dicts.\n\n        :param data: The structured data, assumed to be a dict.\n        :returns: An instance of :class:`~.RedditBase`.\n\n        \"\"\"\n        if {\"conversation\", \"messages\", \"modActions\"}.issubset(data):\n            parser = self.parsers[\"ModmailConversation\"]\n        elif {\"actionTypeId\", \"author\", \"date\"}.issubset(data):\n            # Modmail mod action\n            data = snake_case_keys(data)\n            parser = self.parsers[\"ModmailAction\"]\n        elif {\"bodyMarkdown\", \"isInternal\"}.issubset(data):\n            # Modmail message\n            data = snake_case_keys(data)\n            parser = self.parsers[\"ModmailMessage\"]\n        elif {\"isAdmin\", \"isDeleted\"}.issubset(data):\n            # Modmail author\n            data = snake_case_keys(data)\n            # Prevent clobbering base-36 id\n            del data[\"id\"]\n            data[\"is_subreddit_mod\"] = data.pop(\"is_mod\")\n            parser = self.parsers[self._reddit.config.kinds[\"redditor\"]]\n        elif {\"banStatus\", \"muteStatus\", \"recentComments\"}.issubset(data):\n            # Modmail user\n            data = snake_case_keys(data)\n            data[\"created_string\"] = data.pop(\"created\")\n            parser = self.parsers[self._reddit.config.kinds[\"redditor\"]]\n        elif {\"displayName\", \"id\", \"type\"}.issubset(data):\n            # Modmail subreddit\n            data = snake_case_keys(data)\n            parser = self.parsers[self._reddit.config.kinds[data[\"type\"]]]\n        elif {\"date\", \"id\", \"name\"}.issubset(data) or {\n            \"id\",\n            \"name\",\n            \"permissions\",\n        }.issubset(data):\n            parser = self.parsers[self._reddit.config.kinds[\"redditor\"]]\n        elif {\"text\", \"url\"}.issubset(data):\n            if \"color\" in data or \"linkUrl\" in data:\n                parser = self.parsers[\"Button\"]\n            else:\n                parser = self.parsers[\"MenuLink\"]\n        elif {\"children\", \"text\"}.issubset(data):\n            parser = self.parsers[\"Submenu\"]\n        elif {\"height\", \"url\", \"width\"}.issubset(data):\n            parser = self.parsers[\"Image\"]\n        elif {\"isSubscribed\", \"name\", \"subscribers\"}.issubset(data):\n            # discards icon and subscribed information\n            return self._reddit.subreddit(data[\"name\"])\n        elif {\"authorFlairType\", \"name\"}.issubset(data):\n            # discards flair information\n            return self._reddit.redditor(data[\"name\"])\n        elif {\"parent_id\"}.issubset(data):\n            parser = self.parsers[self._reddit.config.kinds[\"comment\"]]\n        elif \"collection_id\" in data.keys():\n            parser = self.parsers[\"Collection\"]\n        else:\n            if \"user\" in data:\n                parser = self.parsers[self._reddit.config.kinds[\"redditor\"]]\n                data[\"user\"] = parser.parse(\n                    {\"name\": data[\"user\"]}, self._reddit\n                )\n            return data\n        return parser.parse(data, self._reddit)\n\n    def objectify(\n        self, data: Optional[Union[Dict[str, Any], List[Any]]]\n    ) -> Optional[Union[RedditBase, Dict[str, Any], List[Any]]]:\n        \"\"\"Create RedditBase objects from data.\n\n        :param data: The structured data.\n        :returns: An instance of :class:`~.RedditBase`, or ``None`` if\n            given ``data`` is ``None``.\n\n        \"\"\"\n        # pylint: disable=too-many-return-statements\n        if data is None:  # 204 no content\n            return None\n        if isinstance(data, list):\n            return [self.objectify(item) for item in data]\n        if \"kind\" in data and (\n            \"shortName\" in data or data[\"kind\"] in (\"menu\", \"moderators\")\n        ):\n            # This is a widget\n            parser = self.parsers.get(data[\"kind\"], self.parsers[\"widget\"])\n            return parser.parse(data, self._reddit)\n        if {\"kind\", \"data\"}.issubset(data) and data[\"kind\"] in self.parsers:\n            parser = self.parsers[data[\"kind\"]]\n            return parser.parse(data[\"data\"], self._reddit)\n        if \"json\" in data and \"data\" in data[\"json\"]:\n            if \"websocket_url\" in data[\"json\"][\"data\"]:\n                return data\n            if \"things\" in data[\"json\"][\"data\"]:  # Submission.reply\n                return self.objectify(data[\"json\"][\"data\"][\"things\"])\n            if \"url\" in data[\"json\"][\"data\"]:  # Subreddit.submit\n                # The URL is the URL to the submission, so it's removed.\n                del data[\"json\"][\"data\"][\"url\"]\n                parser = self.parsers[self._reddit.config.kinds[\"submission\"]]\n            else:\n                parser = self.parsers[\"LiveUpdateEvent\"]\n            return parser.parse(data[\"json\"][\"data\"], self._reddit)\n        if \"json\" in data and \"errors\" in data[\"json\"]:\n            errors = data[\"json\"][\"errors\"]\n            if len(errors) == 1:\n                raise APIException(*errors[0])\n            assert not errors, (\n                \"Errors did not get raised as an APIException\",\n                errors,\n            )\n        elif isinstance(data, dict):\n            return self._objectify_dict(data)\n\n        return data\n", "path": "praw/objector.py"}, {"content": "\"\"\"Provide the MoreComments class.\"\"\"\nfrom typing import Any, Dict, List, TypeVar, Union\n\nfrom ...const import API_PATH\nfrom ..base import PRAWBase\n\n_MoreComments = TypeVar(\"_MoreComments\")\nComment = TypeVar(\"Comment\")\nReddit = TypeVar(\"Reddit\")\n\n\nclass MoreComments(PRAWBase):\n    \"\"\"A class indicating there are more comments.\"\"\"\n\n    def __init__(self, reddit: Reddit, _data: Dict[str, Any]):\n        \"\"\"Construct an instance of the MoreComments object.\"\"\"\n        self.count = self.parent_id = None\n        self.children = []\n        super().__init__(reddit, _data=_data)\n        self._comments = None\n        self.submission = None\n\n    def __eq__(self, other: Union[str, _MoreComments]) -> bool:\n        \"\"\"Return True if these MoreComments instances are the same.\"\"\"\n        return (\n            isinstance(other, self.__class__)\n            and self.count == other.count\n            and self.children == other.children\n        )\n\n    def __lt__(self, other: _MoreComments) -> bool:\n        \"\"\"Provide a sort order on the MoreComments object.\"\"\"\n        # To work with heapq a \"smaller\" item is the one with the most comments\n        # We are intentionally making the biggest element the smallest element\n        # to turn the min-heap implementation in heapq into a max-heap.\n        return self.count > other.count\n\n    def __repr__(self) -> str:\n        \"\"\"Return a string representation of the MoreComments instance.\"\"\"\n        children = self.children[:4]\n        if len(self.children) > 4:\n            children[-1] = \"...\"\n        return \"<{} count={}, children={!r}>\".format(\n            self.__class__.__name__, self.count, children\n        )\n\n    def _continue_comments(self, update):\n        assert not self.children, \"Please file a bug report with PRAW.\"\n        parent = self._load_comment(self.parent_id.split(\"_\", 1)[1])\n        self._comments = parent.replies\n        if update:\n            for comment in self._comments:\n                comment.submission = self.submission\n        return self._comments\n\n    def _load_comment(self, comment_id):\n        path = \"{}_/{}\".format(\n            API_PATH[\"submission\"].format(id=self.submission.id), comment_id\n        )\n        _, comments = self._reddit.get(\n            path,\n            params={\n                \"limit\": self.submission.comment_limit,\n                \"sort\": self.submission.comment_sort,\n            },\n        )\n        assert (\n            len(comments.children) == 1\n        ), \"Please file a bug report with PRAW.\"\n        return comments.children[0]\n\n    def comments(self, update: bool = True) -> List[Comment]:\n        \"\"\"Fetch and return the comments for a single MoreComments object.\"\"\"\n        if self._comments is None:\n            if self.count == 0:  # Handle 'continue this thread'\n                return self._continue_comments(update)\n            assert self.children, \"Please file a bug report with PRAW.\"\n            data = {\n                \"children\": \",\".join(self.children),\n                \"link_id\": self.submission.fullname,\n                \"sort\": self.submission.comment_sort,\n            }\n            self._comments = self._reddit.post(\n                API_PATH[\"morechildren\"], data=data\n            )\n            if update:\n                for comment in self._comments:\n                    comment.submission = self.submission\n        return self._comments\n", "path": "praw/models/reddit/more.py"}]}