{"action":"created","comment":{"url":"https://api.github.com/repos/oppia/oppia/pulls/comments/191673878","pull_request_review_id":124287298,"id":191673878,"diff_hunk":"@@ -72,3 +66,196 @@ def to_dict(self):\n             'change_cmd': self.change_cmd,\n             'score_category': self.score_category\n         }\n+\n+    @classmethod\n+    def from_dict(cls):\n+        \"\"\"Return a Suggestion object of type from a dict.\"\"\"\n+        raise NotImplementedError(\n+            'Subclasses of BaseSuggestion should implement from_dict.')\n+\n+    def validate(self):\n+        \"\"\"Validates the BaseSuggestion object. Each subclass must implement\n+        this function\n+\n+        Raises:\n+            ValidationError: One or more attributes of the BaseSuggestion object\n+                are invalid.\n+        \"\"\"\n+        if (\n+                self.suggestion_type not in\n+                suggestion_models.SUGGESTION_TYPE_CHOICES):\n+            raise utils.ValidationError(\n+                'Expected suggestion_type to be among allowed choices, '\n+                'recieved %s' % self.suggestion_type)\n+\n+        if self.target_type not in suggestion_models.TARGET_TYPE_CHOICES:\n+            raise utils.ValidationError(\n+                'Expected target_type to be among allowed choices, '\n+                'recieved %s' % self.target_type)\n+\n+        if not isinstance(self.target_id, basestring):\n+            raise utils.ValidationError(\n+                'Expected target_id to be a string, recieved %s' % type(\n+                    self.target_id))\n+\n+        if not isinstance(self.target_version_at_submission, int):\n+            raise utils.ValidationError(\n+                'Expected target_version_at_submission to be an int, '\n+                'recieved %s' % type(self.target_version_at_submission))\n+\n+        if self.status not in suggestion_models.STATUS_CHOICES:\n+            raise utils.ValidationError(\n+                'Expected status to be among allowed choices, '\n+                'recieved %s' % self.status)\n+\n+        if not isinstance(self.author_id, basestring):\n+            raise utils.ValidationError(\n+                'Expected author_id to be a string, recieved %s' % type(\n+                    self.author_id))\n+\n+        if not isinstance(self.assigned_reviewer_id, basestring):\n+            raise utils.ValidationError(\n+                'Expected assigned_reviewer_id to be a string,'\n+                ' recieved %s' % type(self.assigned_reviewer_id))\n+\n+        if not isinstance(self.final_reviewer_id, basestring):\n+            raise utils.ValidationError(\n+                'Expected final_reviewer_id to be a string, recieved %s' % type(\n+                    self.final_reviewer_id))\n+\n+        if not isinstance(self.change_cmd, dict):\n+            raise utils.ValidationError(\n+                'Expected change_cmd to be a dict, recieved %s' % type(\n+                    self.change_cmd))\n+\n+        if not isinstance(self.score_category, basestring):\n+            raise utils.ValidationError(\n+                'Expected score_category to be a string, recieved %s' % type(\n+                    self.score_category))\n+\n+        if (\n+                not suggestion_models.SCORE_CATEGORY_DELIMITER in\n+                self.score_category):\n+            raise utils.ValidationError(\n+                'Expected score_category to be of the form'\n+                ' score_type%sscore_sub_type, recieved %s' %\n+                suggestion_models.SCORE_CATEGORY_DELIMITER, type(\n+                    self.score_category))\n+\n+        if (\n+                self.score_category.split(\n+                    suggestion_models.SCORE_CATEGORY_DELIMITER)[0] not in\n+                suggestion_models.SCORE_TYPE_CHOICES):\n+            raise utils.ValidationError(\n+                'Expected the first part of score_category to be among allowed'\n+                ' choices, recieved %s' % self.score_category.split(\n+                    suggestion_models.SCORE_CATEGORY_DELIMITER)[0])\n+\n+    def accept(self):\n+        \"\"\"Accepts the suggestion. Each subclass must implement this function.\n+        \"\"\"\n+        raise NotImplementedError(\n+            'Subclasses of BaseSuggestion should implement accept.')\n+\n+\n+class SuggestionEditStateContent(BaseSuggestion):\n+    \"\"\"Domain object for a suggestion of type\n+    SUGGESTION_TYPE_EDIT_STATE_CONTENT.\n+    \"\"\"\n+\n+    def __init__( # pylint: disable=super-init-not-called\n+            self, suggestion_id, target_id, target_version_at_submission,\n+            status, author_id, assigned_reviewer_id, final_reviewer_id,\n+            change_cmd, score_category):\n+        \"\"\"Initializes a Suggestion object of type\n+        SUGGESTION_TYPE_EDIT_STATE_CONTENT.\n+        \"\"\"\n+        self.suggestion_id = suggestion_id\n+        self.suggestion_type = (\n+            suggestion_models.SUGGESTION_TYPE_EDIT_STATE_CONTENT)\n+        self.target_type = suggestion_models.TARGET_TYPE_EXPLORATION\n+        self.target_id = target_id\n+        self.target_version_at_submission = target_version_at_submission\n+        self.status = status\n+        self.author_id = author_id\n+        self.assigned_reviewer_id = assigned_reviewer_id\n+        self.final_reviewer_id = final_reviewer_id\n+        self.change_cmd = change_cmd\n+        self.score_category = score_category\n+\n+    def validate(self):\n+        \"\"\"Validates a suggestion object of type\n+        SUGGESTION_TYPE_EDIT_STATE_CONTENT.\n+\n+        Returns:\n+            bool. The validity of the suggestion object.\n+        \"\"\"\n+        super(SuggestionEditStateContent, self).validate()\n+\n+        if 'cmd' not in self.change_cmd:\n+            raise utils.ValidationError(\n+                'Expected change_cmd to contain a cmd key')\n+\n+        if self.change_cmd['cmd'] != exp_domain.CMD_EDIT_STATE_PROPERTY:\n+            raise utils.ValidationError(\n+                'Expected cmd to be %s, recieved %s' % (\n+                    exp_domain.CMD_EDIT_STATE_PROPERTY, self.change_cmd['cmd']))\n+\n+        if 'property_name' not in self.change_cmd:\n+            raise utils.ValidationError(\n+                'Expected change_cmd to contain a property_name key')\n+\n+        if (\n+                self.change_cmd['property_name'] !=\n+                exp_domain.STATE_PROPERTY_CONTENT):\n+            raise utils.ValidationError(\n+                'Expected property_name to be %s, recieved %s' % (\n+                    exp_domain.STATE_PROPERTY_CONTENT,\n+                    self.change_cmd['property_name']))\n+\n+        if 'state_name' not in self.change_cmd:\n+            raise utils.ValidationError(\n+                'Expected change_cmd to contain a state_name key')\n+\n+        states = exp_services.get_exploration_by_id(self.target_id).states\n+        if self.change_cmd['state_name'] not in states:\n+            raise utils.ValidationError(\n+                'Expected %s to be a valid state name' %\n+                self.change_cmd['state_name'])\n+\n+    def accept(self, commit_message):\n+        \"\"\"Accepts the suggestion.\n+\n+        Args:\n+            commit_message: str. The commit message.\n+        \"\"\"\n+        change_list = [self.change_cmd]\n+        exp_services.update_exploration(\n+            self.final_reviewer_id, self.target_type, change_list,\n+            commit_message, is_suggestion=True)\n+\n+    @classmethod\n+    def from_dict(cls, suggestion_dict):\n+        \"\"\"Return a Suggestion object of type from a dict.\n+\n+        Args:\n+            suggestion_dict: dict. The dict representation of the suggestion.\n+\n+        Returns:\n+            BaseSuggestion. The corresponding Suggestion domain object.\n+        \"\"\"\n+        suggestion = cls(\n+            suggestion_dict['suggestion_id'],\n+            suggestion_dict['target_id'],\n+            suggestion_dict['target_version_at_submission'],\n+            suggestion_dict['status'], suggestion_dict['author_id'],\n+            suggestion_dict['assigned_reviewer_id'],\n+            suggestion_dict['final_reviewer_id'], suggestion_dict['change_cmd'],\n+            suggestion_dict['score_category'])\n+\n+        return suggestion\n+\n+\n+SUGGESTION_TYPE_TO_DOMAIN_CLASS = {\n+    suggestion_models.SUGGESTION_TYPE_EDIT_STATE_CONTENT: SuggestionEditStateContent # pylint: disable=line-too-long","path":"core/domain/suggestion_domain.py","position":null,"original_position":239,"commit_id":"20ab5673e55a3b32ac50860849b24054bede0789","original_commit_id":"c938ad0fc0400cf8e2aa163898e365e831409e2d","user":{"login":"nithusha21","id":11898234,"avatar_url":"https://avatars2.githubusercontent.com/u/11898234?v=4","gravatar_id":"","url":"https://api.github.com/users/nithusha21","html_url":"https://github.com/nithusha21","followers_url":"https://api.github.com/users/nithusha21/followers","following_url":"https://api.github.com/users/nithusha21/following{/other_user}","gists_url":"https://api.github.com/users/nithusha21/gists{/gist_id}","starred_url":"https://api.github.com/users/nithusha21/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nithusha21/subscriptions","organizations_url":"https://api.github.com/users/nithusha21/orgs","repos_url":"https://api.github.com/users/nithusha21/repos","events_url":"https://api.github.com/users/nithusha21/events{/privacy}","received_events_url":"https://api.github.com/users/nithusha21/received_events","type":"User","site_admin":false},"body":"Done.","created_at":"2018-05-30T07:58:50Z","updated_at":"2018-05-30T07:58:50Z","html_url":"https://github.com/oppia/oppia/pull/4989#discussion_r191673878","pull_request_url":"https://api.github.com/repos/oppia/oppia/pulls/4989","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/oppia/oppia/pulls/comments/191673878"},"html":{"href":"https://github.com/oppia/oppia/pull/4989#discussion_r191673878"},"pull_request":{"href":"https://api.github.com/repos/oppia/oppia/pulls/4989"}},"in_reply_to_id":191639596},"pull_request":{"url":"https://api.github.com/repos/oppia/oppia/pulls/4989","id":190906775,"html_url":"https://github.com/oppia/oppia/pull/4989","diff_url":"https://github.com/oppia/oppia/pull/4989.diff","patch_url":"https://github.com/oppia/oppia/pull/4989.patch","issue_url":"https://api.github.com/repos/oppia/oppia/issues/4989","number":4989,"state":"open","locked":false,"title":"Generalized Review System: Milestone 1 - Changes to suggestion_domain","user":{"login":"nithusha21","id":11898234,"avatar_url":"https://avatars2.githubusercontent.com/u/11898234?v=4","gravatar_id":"","url":"https://api.github.com/users/nithusha21","html_url":"https://github.com/nithusha21","followers_url":"https://api.github.com/users/nithusha21/followers","following_url":"https://api.github.com/users/nithusha21/following{/other_user}","gists_url":"https://api.github.com/users/nithusha21/gists{/gist_id}","starred_url":"https://api.github.com/users/nithusha21/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nithusha21/subscriptions","organizations_url":"https://api.github.com/users/nithusha21/orgs","repos_url":"https://api.github.com/users/nithusha21/repos","events_url":"https://api.github.com/users/nithusha21/events{/privacy}","received_events_url":"https://api.github.com/users/nithusha21/received_events","type":"User","site_admin":false},"body":"## Explanation\r\nReference: https://github.com/oppia/oppia/pull/4982#discussion_r191069473\r\n\r\nAs noted that the validation can be kept specific to a type of suggestion by creating sub classes of a BaseSuggestion class for various types of suggestions. This PR implements a SuggestionEditStateContent class which is a sub class of BaseSuggestion. \r\n\r\nPTAL @anmolshkl and @seanlip \r\n\r\n## Checklist\r\n- [ ] The PR title starts with \"Fix #bugnum: \", followed by a short, clear summary of the changes.\r\n- [ ] The PR explanation includes the words \"Fixes #bugnum: ...\".\r\n- [x] The linter/Karma presubmit checks have passed.\r\n  - These should run automatically, but if not, you can manually trigger them locally using `python scripts/pre_commit_linter.py` and `bash scripts/run_frontend_tests.sh`.\r\n- [x] The PR is made from a branch that's **not** called \"develop\".\r\n- [x] The PR follows the [style guide](https://github.com/oppia/oppia/wiki/Coding-style-guide).\r\n- [x] The PR is assigned to an appropriate reviewer.\r\n  - If you're a new contributor, please ask on [Gitter](https://gitter.im/oppia/oppia-chat) for someone to assign a reviewer.\r\n  - If you're not sure who the appropriate reviewer is, please assign to the issue's \"owner\" -- see the \"talk-to\" label on the issue.\r\n","created_at":"2018-05-28T11:30:33Z","updated_at":"2018-05-30T07:58:50Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a11817ab8b6896f647daa33f53de9e9540e1885d","assignee":{"login":"seanlip","id":10575562,"avatar_url":"https://avatars0.githubusercontent.com/u/10575562?v=4","gravatar_id":"","url":"https://api.github.com/users/seanlip","html_url":"https://github.com/seanlip","followers_url":"https://api.github.com/users/seanlip/followers","following_url":"https://api.github.com/users/seanlip/following{/other_user}","gists_url":"https://api.github.com/users/seanlip/gists{/gist_id}","starred_url":"https://api.github.com/users/seanlip/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/seanlip/subscriptions","organizations_url":"https://api.github.com/users/seanlip/orgs","repos_url":"https://api.github.com/users/seanlip/repos","events_url":"https://api.github.com/users/seanlip/events{/privacy}","received_events_url":"https://api.github.com/users/seanlip/received_events","type":"User","site_admin":false},"assignees":[{"login":"seanlip","id":10575562,"avatar_url":"https://avatars0.githubusercontent.com/u/10575562?v=4","gravatar_id":"","url":"https://api.github.com/users/seanlip","html_url":"https://github.com/seanlip","followers_url":"https://api.github.com/users/seanlip/followers","following_url":"https://api.github.com/users/seanlip/following{/other_user}","gists_url":"https://api.github.com/users/seanlip/gists{/gist_id}","starred_url":"https://api.github.com/users/seanlip/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/seanlip/subscriptions","organizations_url":"https://api.github.com/users/seanlip/orgs","repos_url":"https://api.github.com/users/seanlip/repos","events_url":"https://api.github.com/users/seanlip/events{/privacy}","received_events_url":"https://api.github.com/users/seanlip/received_events","type":"User","site_admin":false}],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/oppia/oppia/pulls/4989/commits","review_comments_url":"https://api.github.com/repos/oppia/oppia/pulls/4989/comments","review_comment_url":"https://api.github.com/repos/oppia/oppia/pulls/comments{/number}","comments_url":"https://api.github.com/repos/oppia/oppia/issues/4989/comments","statuses_url":"https://api.github.com/repos/oppia/oppia/statuses/20ab5673e55a3b32ac50860849b24054bede0789","head":{"label":"nithusha21:sub-classing-suggestion-domain","ref":"sub-classing-suggestion-domain","sha":"20ab5673e55a3b32ac50860849b24054bede0789","user":{"login":"nithusha21","id":11898234,"avatar_url":"https://avatars2.githubusercontent.com/u/11898234?v=4","gravatar_id":"","url":"https://api.github.com/users/nithusha21","html_url":"https://github.com/nithusha21","followers_url":"https://api.github.com/users/nithusha21/followers","following_url":"https://api.github.com/users/nithusha21/following{/other_user}","gists_url":"https://api.github.com/users/nithusha21/gists{/gist_id}","starred_url":"https://api.github.com/users/nithusha21/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nithusha21/subscriptions","organizations_url":"https://api.github.com/users/nithusha21/orgs","repos_url":"https://api.github.com/users/nithusha21/repos","events_url":"https://api.github.com/users/nithusha21/events{/privacy}","received_events_url":"https://api.github.com/users/nithusha21/received_events","type":"User","site_admin":false},"repo":{"id":111784747,"name":"oppia","full_name":"nithusha21/oppia","owner":{"login":"nithusha21","id":11898234,"avatar_url":"https://avatars2.githubusercontent.com/u/11898234?v=4","gravatar_id":"","url":"https://api.github.com/users/nithusha21","html_url":"https://github.com/nithusha21","followers_url":"https://api.github.com/users/nithusha21/followers","following_url":"https://api.github.com/users/nithusha21/following{/other_user}","gists_url":"https://api.github.com/users/nithusha21/gists{/gist_id}","starred_url":"https://api.github.com/users/nithusha21/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nithusha21/subscriptions","organizations_url":"https://api.github.com/users/nithusha21/orgs","repos_url":"https://api.github.com/users/nithusha21/repos","events_url":"https://api.github.com/users/nithusha21/events{/privacy}","received_events_url":"https://api.github.com/users/nithusha21/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/nithusha21/oppia","description":"Tool for collaboratively building interactive lessons.","fork":true,"url":"https://api.github.com/repos/nithusha21/oppia","forks_url":"https://api.github.com/repos/nithusha21/oppia/forks","keys_url":"https://api.github.com/repos/nithusha21/oppia/keys{/key_id}","collaborators_url":"https://api.github.com/repos/nithusha21/oppia/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/nithusha21/oppia/teams","hooks_url":"https://api.github.com/repos/nithusha21/oppia/hooks","issue_events_url":"https://api.github.com/repos/nithusha21/oppia/issues/events{/number}","events_url":"https://api.github.com/repos/nithusha21/oppia/events","assignees_url":"https://api.github.com/repos/nithusha21/oppia/assignees{/user}","branches_url":"https://api.github.com/repos/nithusha21/oppia/branches{/branch}","tags_url":"https://api.github.com/repos/nithusha21/oppia/tags","blobs_url":"https://api.github.com/repos/nithusha21/oppia/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/nithusha21/oppia/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/nithusha21/oppia/git/refs{/sha}","trees_url":"https://api.github.com/repos/nithusha21/oppia/git/trees{/sha}","statuses_url":"https://api.github.com/repos/nithusha21/oppia/statuses/{sha}","languages_url":"https://api.github.com/repos/nithusha21/oppia/languages","stargazers_url":"https://api.github.com/repos/nithusha21/oppia/stargazers","contributors_url":"https://api.github.com/repos/nithusha21/oppia/contributors","subscribers_url":"https://api.github.com/repos/nithusha21/oppia/subscribers","subscription_url":"https://api.github.com/repos/nithusha21/oppia/subscription","commits_url":"https://api.github.com/repos/nithusha21/oppia/commits{/sha}","git_commits_url":"https://api.github.com/repos/nithusha21/oppia/git/commits{/sha}","comments_url":"https://api.github.com/repos/nithusha21/oppia/comments{/number}","issue_comment_url":"https://api.github.com/repos/nithusha21/oppia/issues/comments{/number}","contents_url":"https://api.github.com/repos/nithusha21/oppia/contents/{+path}","compare_url":"https://api.github.com/repos/nithusha21/oppia/compare/{base}...{head}","merges_url":"https://api.github.com/repos/nithusha21/oppia/merges","archive_url":"https://api.github.com/repos/nithusha21/oppia/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/nithusha21/oppia/downloads","issues_url":"https://api.github.com/repos/nithusha21/oppia/issues{/number}","pulls_url":"https://api.github.com/repos/nithusha21/oppia/pulls{/number}","milestones_url":"https://api.github.com/repos/nithusha21/oppia/milestones{/number}","notifications_url":"https://api.github.com/repos/nithusha21/oppia/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/nithusha21/oppia/labels{/name}","releases_url":"https://api.github.com/repos/nithusha21/oppia/releases{/id}","deployments_url":"https://api.github.com/repos/nithusha21/oppia/deployments","created_at":"2017-11-23T08:43:13Z","updated_at":"2018-05-28T14:08:19Z","pushed_at":"2018-05-30T07:56:37Z","git_url":"git://github.com/nithusha21/oppia.git","ssh_url":"git@github.com:nithusha21/oppia.git","clone_url":"https://github.com/nithusha21/oppia.git","svn_url":"https://github.com/nithusha21/oppia","homepage":"https://www.oppia.org","size":103143,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_projects":true,"has_downloads":false,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":0,"open_issues":0,"watchers":0,"default_branch":"develop"}},"base":{"label":"oppia:develop","ref":"develop","sha":"afe379255de9cc8f8c555595e389850b5412bae9","user":{"login":"oppia","id":11620230,"avatar_url":"https://avatars1.githubusercontent.com/u/11620230?v=4","gravatar_id":"","url":"https://api.github.com/users/oppia","html_url":"https://github.com/oppia","followers_url":"https://api.github.com/users/oppia/followers","following_url":"https://api.github.com/users/oppia/following{/other_user}","gists_url":"https://api.github.com/users/oppia/gists{/gist_id}","starred_url":"https://api.github.com/users/oppia/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/oppia/subscriptions","organizations_url":"https://api.github.com/users/oppia/orgs","repos_url":"https://api.github.com/users/oppia/repos","events_url":"https://api.github.com/users/oppia/events{/privacy}","received_events_url":"https://api.github.com/users/oppia/received_events","type":"Organization","site_admin":false},"repo":{"id":40687563,"name":"oppia","full_name":"oppia/oppia","owner":{"login":"oppia","id":11620230,"avatar_url":"https://avatars1.githubusercontent.com/u/11620230?v=4","gravatar_id":"","url":"https://api.github.com/users/oppia","html_url":"https://github.com/oppia","followers_url":"https://api.github.com/users/oppia/followers","following_url":"https://api.github.com/users/oppia/following{/other_user}","gists_url":"https://api.github.com/users/oppia/gists{/gist_id}","starred_url":"https://api.github.com/users/oppia/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/oppia/subscriptions","organizations_url":"https://api.github.com/users/oppia/orgs","repos_url":"https://api.github.com/users/oppia/repos","events_url":"https://api.github.com/users/oppia/events{/privacy}","received_events_url":"https://api.github.com/users/oppia/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/oppia/oppia","description":"Tool for collaboratively building interactive lessons.","fork":false,"url":"https://api.github.com/repos/oppia/oppia","forks_url":"https://api.github.com/repos/oppia/oppia/forks","keys_url":"https://api.github.com/repos/oppia/oppia/keys{/key_id}","collaborators_url":"https://api.github.com/repos/oppia/oppia/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/oppia/oppia/teams","hooks_url":"https://api.github.com/repos/oppia/oppia/hooks","issue_events_url":"https://api.github.com/repos/oppia/oppia/issues/events{/number}","events_url":"https://api.github.com/repos/oppia/oppia/events","assignees_url":"https://api.github.com/repos/oppia/oppia/assignees{/user}","branches_url":"https://api.github.com/repos/oppia/oppia/branches{/branch}","tags_url":"https://api.github.com/repos/oppia/oppia/tags","blobs_url":"https://api.github.com/repos/oppia/oppia/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/oppia/oppia/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/oppia/oppia/git/refs{/sha}","trees_url":"https://api.github.com/repos/oppia/oppia/git/trees{/sha}","statuses_url":"https://api.github.com/repos/oppia/oppia/statuses/{sha}","languages_url":"https://api.github.com/repos/oppia/oppia/languages","stargazers_url":"https://api.github.com/repos/oppia/oppia/stargazers","contributors_url":"https://api.github.com/repos/oppia/oppia/contributors","subscribers_url":"https://api.github.com/repos/oppia/oppia/subscribers","subscription_url":"https://api.github.com/repos/oppia/oppia/subscription","commits_url":"https://api.github.com/repos/oppia/oppia/commits{/sha}","git_commits_url":"https://api.github.com/repos/oppia/oppia/git/commits{/sha}","comments_url":"https://api.github.com/repos/oppia/oppia/comments{/number}","issue_comment_url":"https://api.github.com/repos/oppia/oppia/issues/comments{/number}","contents_url":"https://api.github.com/repos/oppia/oppia/contents/{+path}","compare_url":"https://api.github.com/repos/oppia/oppia/compare/{base}...{head}","merges_url":"https://api.github.com/repos/oppia/oppia/merges","archive_url":"https://api.github.com/repos/oppia/oppia/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/oppia/oppia/downloads","issues_url":"https://api.github.com/repos/oppia/oppia/issues{/number}","pulls_url":"https://api.github.com/repos/oppia/oppia/pulls{/number}","milestones_url":"https://api.github.com/repos/oppia/oppia/milestones{/number}","notifications_url":"https://api.github.com/repos/oppia/oppia/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/oppia/oppia/labels{/name}","releases_url":"https://api.github.com/repos/oppia/oppia/releases{/id}","deployments_url":"https://api.github.com/repos/oppia/oppia/deployments","created_at":"2015-08-14T00:16:14Z","updated_at":"2018-05-29T18:56:27Z","pushed_at":"2018-05-30T07:56:39Z","git_url":"git://github.com/oppia/oppia.git","ssh_url":"git@github.com:oppia/oppia.git","clone_url":"https://github.com/oppia/oppia.git","svn_url":"https://github.com/oppia/oppia","homepage":"https://www.oppia.org","size":103239,"stargazers_count":653,"watchers_count":653,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":false,"has_wiki":true,"has_pages":false,"forks_count":631,"mirror_url":null,"archived":false,"open_issues_count":306,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":631,"open_issues":306,"watchers":653,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/oppia/oppia/pulls/4989"},"html":{"href":"https://github.com/oppia/oppia/pull/4989"},"issue":{"href":"https://api.github.com/repos/oppia/oppia/issues/4989"},"comments":{"href":"https://api.github.com/repos/oppia/oppia/issues/4989/comments"},"review_comments":{"href":"https://api.github.com/repos/oppia/oppia/pulls/4989/comments"},"review_comment":{"href":"https://api.github.com/repos/oppia/oppia/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/oppia/oppia/pulls/4989/commits"},"statuses":{"href":"https://api.github.com/repos/oppia/oppia/statuses/20ab5673e55a3b32ac50860849b24054bede0789"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"nithusha21"}}