{"action":"created","comment":{"url":"https://api.github.com/repos/gregoil/rotest/pulls/comments/177966363","pull_request_review_id":107713679,"id":177966363,"diff_hunk":"@@ -0,0 +1,358 @@\n+\"\"\"Utils module for pretty-printing the logs.\"\"\"\n+import os\n+import sys\n+import math\n+import struct\n+from abc import ABCMeta, abstractmethod\n+\n+import enum\n+from termcolor import colored\n+\n+from rotest.core.case import TestCase\n+from rotest.core.flow import TestFlow\n+from rotest.core.suite import TestSuite\n+from rotest.core.block import TestBlock\n+\n+\n+class TitleConfiguration(object):\n+    \"\"\"Interface for specifying the colors that will be printed in a test.\n+\n+    Attributes:\n+        result (TestResult): result of the test.\n+    \"\"\"\n+    __metaclass__ = ABCMeta\n+\n+    def __init__(self, result):\n+        self.result = result\n+\n+    @abstractmethod\n+    def decoration_character(self):\n+        \"\"\"Define the character that will be used to decorate the test.\n+\n+        Returns:\n+            str. character to be printed in the log.\n+        \"\"\"\n+        pass\n+\n+    @abstractmethod\n+    def decoration_color(self):\n+        \"\"\"Define the color of the decoration.\n+\n+        Returns:\n+            str. name of the color to color the decoration.\n+        \"\"\"\n+        pass\n+\n+    @abstractmethod\n+    def test_type_color(self):\n+        \"\"\"Define the color of the test type.\n+\n+        Returns:\n+            str. name of the color to color the test type(\"Block\"/\"Flow\")\n+        \"\"\"\n+        pass\n+\n+    @abstractmethod\n+    def test_name_color(self):\n+        \"\"\"Define the color of the test's name.\n+\n+        Returns:\n+            str. name of the color to color the test name.\n+        \"\"\"\n+        pass\n+\n+    @abstractmethod\n+    def has_multi_line_decoration(self):\n+        \"\"\"Determine whether or not this test has a multi-line decoration.\n+\n+        Returns:\n+            bool. True if this tests has multiple lines of decoration.\n+        \"\"\"\n+        pass\n+\n+    @abstractmethod\n+    def test_result_color(self):\n+        \"\"\"Define the color of the test's result.\n+\n+        Returns:\n+            str. name of the color to color the test name.\n+        \"\"\"\n+        pass\n+\n+    @staticmethod\n+    def from_test(test, result):\n+        \"\"\"Return a configuration matching the test supplied.\n+\n+        Returns:\n+            TestConfiguration. configuration that matches a given test.\n+\n+        Raises:\n+            TypeError: If given any test that is not an AbstractTest.\n+        \"\"\"\n+        if test.IS_COMPLEX:\n+            return ComplexTitleConfiguration(result)\n+\n+        else:\n+            return NonComplexTitleConfiguration(result)\n+\n+\n+class NonComplexTitleConfiguration(TitleConfiguration):\n+    def has_multi_line_decoration(self):\n+        return False\n+\n+    def decoration_character(self):\n+        return \"-\"\n+\n+    def decoration_color(self):\n+        colors = {\n+            TestResult.failure: \"red\",\n+            TestResult.error: \"red\",\n+            TestResult.skip: \"white\",\n+            TestResult.success: \"green\",\n+            TestResult.started: \"white\",\n+        }\n+\n+        return colors[self.result]\n+\n+    def test_type_color(self):\n+        colors = {\n+            TestResult.failure: \"red\",\n+            TestResult.error: \"red\",\n+            TestResult.skip: \"white\",\n+            TestResult.success: \"green\",\n+            TestResult.started: \"white\",\n+        }\n+\n+        return colors[self.result]\n+\n+    def test_result_color(self):\n+        colors = {\n+            TestResult.failure: \"red\",\n+            TestResult.error: \"red\",\n+            TestResult.skip: \"white\",\n+            TestResult.success: \"green\",\n+            TestResult.started: \"white\",\n+        }\n+\n+        return colors[self.result]\n+\n+    def test_name_color(self):\n+        colors = {\n+            TestResult.failure: \"red\",\n+            TestResult.error: \"red\",\n+            TestResult.skip: \"yellow\",\n+            TestResult.success: \"green\",\n+            TestResult.started: \"cyan\"\n+        }\n+        return colors[self.result]\n+\n+\n+class ComplexTitleConfiguration(TitleConfiguration):\n+    def has_multi_line_decoration(self):\n+        return True\n+\n+    def decoration_character(self):\n+        return \"=\"\n+\n+    def decoration_color(self):\n+        colors = {\n+            TestResult.failure: \"red\",\n+            TestResult.error: \"red\",\n+            TestResult.skip: \"white\",\n+            TestResult.success: \"green\",\n+            TestResult.started: \"white\",\n+        }\n+\n+        return colors[self.result]\n+\n+    def test_result_color(self):\n+        colors = {\n+            TestResult.failure: \"red\",\n+            TestResult.error: \"red\",\n+            TestResult.skip: \"white\",\n+            TestResult.success: \"green\",\n+            TestResult.started: \"white\",\n+        }\n+\n+        return colors[self.result]\n+\n+    def test_type_color(self):\n+        colors = {\n+            TestResult.failure: \"red\",\n+            TestResult.error: \"red\",\n+            TestResult.skip: \"white\",\n+            TestResult.success: \"green\",\n+            TestResult.started: \"white\",\n+        }\n+\n+        return colors[self.result]\n+\n+    def test_name_color(self):\n+        colors = {\n+            TestResult.failure: \"red\",\n+            TestResult.error: \"red\",\n+            TestResult.skip: \"yellow\",\n+            TestResult.success: \"green\",\n+            TestResult.started: \"blue\"\n+        }\n+        return colors[self.result]\n+\n+\n+class TestResult(enum.Enum):\n+    success = \"success\"\n+    skip = \"skip\"\n+    error = \"error\"\n+    failure = \"fail\"\n+    started = \"started\"\n+    block_started = \"block-started\"\n+    flow_started = \"flow-started\"\n+\n+    def __str__(self):\n+        return str(self.value)\n+\n+    def __eq__(self, other):\n+        return str(self) == other\n+\n+\n+class Pretty(object):\n+    \"\"\"Title with decoration.\n+\n+    Attributes:\n+        test (AbstractTest): encapsulated test to generate it's title.\n+        result (TestResult): result that the tests ended with (or didn't end).\n+        configuration (TitleConfiguration): title's configuration of colors.\n+    \"\"\"\n+    def __init__(self, test, result):\n+        self.test = test\n+        self.result = result\n+        self.configuration = TitleConfiguration.from_test(test, result)\n+\n+    def __str__(self):\n+        line = (\"{multi_line_decoration}\"\n+                \"{decoration_left}\"\n+                \" {test_type}: {test_name} ({result}) \"\n+                \"{decoration_right}\"\n+                \"{multi_line_decoration}\")\n+\n+        return line.format(\n+            multi_line_decoration=self.multi_line_decoration(),\n+            decoration_left=self.left_decoration(),\n+            test_type=self.test_type(),\n+            test_name=self.test_name(),\n+            result=self.test_result(),\n+            decoration_right=self.right_decoration()\n+        )\n+\n+    def left_decoration(self):\n+        decoration_color = self.configuration.decoration_color()\n+        decoration_char = self.configuration.decoration_character()\n+        left_decoration_length = self._whole_decoration_line_width() / 2\n+\n+        return colored(left_decoration_length * decoration_char,\n+                       decoration_color)\n+\n+    def right_decoration(self):\n+        decoration_color = self.configuration.decoration_color()\n+        decoration_char = self.configuration.decoration_character()\n+        right_decoration_length = int(\n+            math.ceil(float(self._whole_decoration_line_width()) / 2))\n+\n+        return colored(right_decoration_length * decoration_char,\n+                       decoration_color)\n+\n+    def multi_line_decoration(self):\n+        if self.configuration.has_multi_line_decoration():\n+            decoration_char = self.configuration.decoration_character()\n+            decoration_color = self.configuration.decoration_color()\n+            line_width = get_columns()\n+            return colored(os.linesep +\n+                           (decoration_char * line_width) +\n+                           os.linesep,\n+                           decoration_color)\n+\n+        else:\n+            return os.linesep\n+\n+    def test_result(self):\n+        result_text = self._test_result_uncolored()\n+        result_color = self.configuration.test_result_color()\n+        return colored(result_text, color=result_color)\n+\n+    def test_name(self):\n+        name = self._test_name_uncolored()\n+        color = self.configuration.test_name_color()\n+        return colored(name, color=color)\n+\n+    def test_type(self):\n+        test_type = self._test_type_uncolored()\n+        color = self.configuration.test_type_color()\n+        return colored(test_type, color=color, attrs=[\"bold\"])\n+\n+    def _test_type_uncolored(self):\n+        if isinstance(self.test, TestBlock):\n+            return \"Block\"\n+\n+        if isinstance(self.test, TestFlow):\n+            return \"Flow\"\n+\n+        if isinstance(self.test, TestCase):\n+            return \"Case\"\n+\n+        if isinstance(self.test, TestSuite):\n+            return \"Suite\"\n+\n+        raise TypeError(\"Can't pretty print test %r, \"\n+                        \"unsupported type\" % self.test)\n+\n+    def _test_name_uncolored(self):\n+        return self.test.__class__.__name__\n+\n+    def _test_result_uncolored(self):\n+        return str(self.result).capitalize()\n+\n+    def _whole_decoration_line_width(self):\n+        \"\"\"Return the width of the whole decoration line.\n+            That means the left and right decoration combined.\n+            To be used for calculating the left and right decorations.\n+\n+            Note:\n+                There is a need to calculate left and right decoration\n+                differently because it is desired to fill the entire screen\n+                even if the screen width is uneven.\n+        \"\"\"\n+        no_decoration_template = \" {test_type}: {test_name} ({result}) \"\n+        text_without_colors = no_decoration_template.format(\n+            test_type=self._test_type_uncolored(),\n+            test_name=self._test_name_uncolored(),\n+            result=self._test_result_uncolored()\n+        )\n+\n+        console_width = get_columns()\n+        return console_width - len(text_without_colors)\n+\n+\n+def get_columns():\n+    \"\"\"Return the amount of columns in the current terminal.\n+\n+    Returns:\n+        int. width of a single row in the current terminal.\n+    \"\"\"\n+    if sys.platform in (\"linux\", \"linux2\", \"darwin\"):\n+        # Both OS X (darwin) and Linux support the 'stty' command\n+        _, columns = os.popen(\"stty size\").read().split()\n+        columns = int(columns)\n+        return columns\n+\n+    if sys.platform == \"win32\":\n+        from ctypes import windll, create_string_buffer\n+        handle = windll.kernel32.GetStdHandle(-12)  # stderr\n+        info_buffer = create_string_buffer(22)\n+        result = windll.kernel32.GetConsoleScreenBufferInfo(handle,\n+                                                            info_buffer)\n+        if result:\n+            parsed_result = struct.unpack(\"hhhhHhhhhhh\", info_buffer.raw)","path":"src/rotest/core/utils/pretty.py","position":353,"original_position":353,"commit_id":"3714060a79cf0822c39bfd4a33b9b9f807135789","original_commit_id":"52f8a77d0554b38949226366f15b06fd385eeda1","user":{"login":"rinslow","id":12800016,"avatar_url":"https://avatars3.githubusercontent.com/u/12800016?v=4","gravatar_id":"","url":"https://api.github.com/users/rinslow","html_url":"https://github.com/rinslow","followers_url":"https://api.github.com/users/rinslow/followers","following_url":"https://api.github.com/users/rinslow/following{/other_user}","gists_url":"https://api.github.com/users/rinslow/gists{/gist_id}","starred_url":"https://api.github.com/users/rinslow/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rinslow/subscriptions","organizations_url":"https://api.github.com/users/rinslow/orgs","repos_url":"https://api.github.com/users/rinslow/repos","events_url":"https://api.github.com/users/rinslow/events{/privacy}","received_events_url":"https://api.github.com/users/rinslow/received_events","type":"User","site_admin":false},"body":"I looked through and through for ways to get console size in win32, I couldn't find anything that worked. I'll push now but I'll try again","created_at":"2018-03-29T06:51:32Z","updated_at":"2018-03-29T06:51:48Z","html_url":"https://github.com/gregoil/rotest/pull/43#discussion_r177966363","pull_request_url":"https://api.github.com/repos/gregoil/rotest/pulls/43","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/gregoil/rotest/pulls/comments/177966363"},"html":{"href":"https://github.com/gregoil/rotest/pull/43#discussion_r177966363"},"pull_request":{"href":"https://api.github.com/repos/gregoil/rotest/pulls/43"}},"in_reply_to_id":177530524},"pull_request":{"url":"https://api.github.com/repos/gregoil/rotest/pulls/43","id":177438135,"html_url":"https://github.com/gregoil/rotest/pull/43","diff_url":"https://github.com/gregoil/rotest/pull/43.diff","patch_url":"https://github.com/gregoil/rotest/pull/43.patch","issue_url":"https://api.github.com/repos/gregoil/rotest/issues/43","number":43,"state":"open","locked":false,"title":"Feature/output handler pretty","user":{"login":"rinslow","id":12800016,"avatar_url":"https://avatars3.githubusercontent.com/u/12800016?v=4","gravatar_id":"","url":"https://api.github.com/users/rinslow","html_url":"https://github.com/rinslow","followers_url":"https://api.github.com/users/rinslow/followers","following_url":"https://api.github.com/users/rinslow/following{/other_user}","gists_url":"https://api.github.com/users/rinslow/gists{/gist_id}","starred_url":"https://api.github.com/users/rinslow/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rinslow/subscriptions","organizations_url":"https://api.github.com/users/rinslow/orgs","repos_url":"https://api.github.com/users/rinslow/repos","events_url":"https://api.github.com/users/rinslow/events{/privacy}","received_events_url":"https://api.github.com/users/rinslow/received_events","type":"User","site_admin":false},"body":"Added an (on-by-default) output handler called \"pretty\". \r\nIt decorates the beginning and ending of tests, creating an easy-to-identify patterns in the log.","created_at":"2018-03-26T12:59:51Z","updated_at":"2018-03-29T06:51:48Z","closed_at":null,"merged_at":null,"merge_commit_sha":"39891ac015ce78500b7e336e9bd844fd781277a3","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/gregoil/rotest/pulls/43/commits","review_comments_url":"https://api.github.com/repos/gregoil/rotest/pulls/43/comments","review_comment_url":"https://api.github.com/repos/gregoil/rotest/pulls/comments{/number}","comments_url":"https://api.github.com/repos/gregoil/rotest/issues/43/comments","statuses_url":"https://api.github.com/repos/gregoil/rotest/statuses/3714060a79cf0822c39bfd4a33b9b9f807135789","head":{"label":"rinslow:feature/output-handler-pretty","ref":"feature/output-handler-pretty","sha":"3714060a79cf0822c39bfd4a33b9b9f807135789","user":{"login":"rinslow","id":12800016,"avatar_url":"https://avatars3.githubusercontent.com/u/12800016?v=4","gravatar_id":"","url":"https://api.github.com/users/rinslow","html_url":"https://github.com/rinslow","followers_url":"https://api.github.com/users/rinslow/followers","following_url":"https://api.github.com/users/rinslow/following{/other_user}","gists_url":"https://api.github.com/users/rinslow/gists{/gist_id}","starred_url":"https://api.github.com/users/rinslow/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rinslow/subscriptions","organizations_url":"https://api.github.com/users/rinslow/orgs","repos_url":"https://api.github.com/users/rinslow/repos","events_url":"https://api.github.com/users/rinslow/events{/privacy}","received_events_url":"https://api.github.com/users/rinslow/received_events","type":"User","site_admin":false},"repo":{"id":115143470,"name":"rotest","full_name":"rinslow/rotest","owner":{"login":"rinslow","id":12800016,"avatar_url":"https://avatars3.githubusercontent.com/u/12800016?v=4","gravatar_id":"","url":"https://api.github.com/users/rinslow","html_url":"https://github.com/rinslow","followers_url":"https://api.github.com/users/rinslow/followers","following_url":"https://api.github.com/users/rinslow/following{/other_user}","gists_url":"https://api.github.com/users/rinslow/gists{/gist_id}","starred_url":"https://api.github.com/users/rinslow/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rinslow/subscriptions","organizations_url":"https://api.github.com/users/rinslow/orgs","repos_url":"https://api.github.com/users/rinslow/repos","events_url":"https://api.github.com/users/rinslow/events{/privacy}","received_events_url":"https://api.github.com/users/rinslow/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/rinslow/rotest","description":"Resource oriented testing framework","fork":true,"url":"https://api.github.com/repos/rinslow/rotest","forks_url":"https://api.github.com/repos/rinslow/rotest/forks","keys_url":"https://api.github.com/repos/rinslow/rotest/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rinslow/rotest/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rinslow/rotest/teams","hooks_url":"https://api.github.com/repos/rinslow/rotest/hooks","issue_events_url":"https://api.github.com/repos/rinslow/rotest/issues/events{/number}","events_url":"https://api.github.com/repos/rinslow/rotest/events","assignees_url":"https://api.github.com/repos/rinslow/rotest/assignees{/user}","branches_url":"https://api.github.com/repos/rinslow/rotest/branches{/branch}","tags_url":"https://api.github.com/repos/rinslow/rotest/tags","blobs_url":"https://api.github.com/repos/rinslow/rotest/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rinslow/rotest/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rinslow/rotest/git/refs{/sha}","trees_url":"https://api.github.com/repos/rinslow/rotest/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rinslow/rotest/statuses/{sha}","languages_url":"https://api.github.com/repos/rinslow/rotest/languages","stargazers_url":"https://api.github.com/repos/rinslow/rotest/stargazers","contributors_url":"https://api.github.com/repos/rinslow/rotest/contributors","subscribers_url":"https://api.github.com/repos/rinslow/rotest/subscribers","subscription_url":"https://api.github.com/repos/rinslow/rotest/subscription","commits_url":"https://api.github.com/repos/rinslow/rotest/commits{/sha}","git_commits_url":"https://api.github.com/repos/rinslow/rotest/git/commits{/sha}","comments_url":"https://api.github.com/repos/rinslow/rotest/comments{/number}","issue_comment_url":"https://api.github.com/repos/rinslow/rotest/issues/comments{/number}","contents_url":"https://api.github.com/repos/rinslow/rotest/contents/{+path}","compare_url":"https://api.github.com/repos/rinslow/rotest/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rinslow/rotest/merges","archive_url":"https://api.github.com/repos/rinslow/rotest/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rinslow/rotest/downloads","issues_url":"https://api.github.com/repos/rinslow/rotest/issues{/number}","pulls_url":"https://api.github.com/repos/rinslow/rotest/pulls{/number}","milestones_url":"https://api.github.com/repos/rinslow/rotest/milestones{/number}","notifications_url":"https://api.github.com/repos/rinslow/rotest/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rinslow/rotest/labels{/name}","releases_url":"https://api.github.com/repos/rinslow/rotest/releases{/id}","deployments_url":"https://api.github.com/repos/rinslow/rotest/deployments","created_at":"2017-12-22T19:10:35Z","updated_at":"2018-03-25T11:55:41Z","pushed_at":"2018-03-28T20:23:17Z","git_url":"git://github.com/rinslow/rotest.git","ssh_url":"git@github.com:rinslow/rotest.git","clone_url":"https://github.com/rinslow/rotest.git","svn_url":"https://github.com/rinslow/rotest","homepage":null,"size":509,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":null,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"gregoil:master","ref":"master","sha":"b94f98f519e1f1f71c36c559f78cfc3924708b27","user":{"login":"gregoil","id":29352269,"avatar_url":"https://avatars2.githubusercontent.com/u/29352269?v=4","gravatar_id":"","url":"https://api.github.com/users/gregoil","html_url":"https://github.com/gregoil","followers_url":"https://api.github.com/users/gregoil/followers","following_url":"https://api.github.com/users/gregoil/following{/other_user}","gists_url":"https://api.github.com/users/gregoil/gists{/gist_id}","starred_url":"https://api.github.com/users/gregoil/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gregoil/subscriptions","organizations_url":"https://api.github.com/users/gregoil/orgs","repos_url":"https://api.github.com/users/gregoil/repos","events_url":"https://api.github.com/users/gregoil/events{/privacy}","received_events_url":"https://api.github.com/users/gregoil/received_events","type":"User","site_admin":false},"repo":{"id":94022519,"name":"rotest","full_name":"gregoil/rotest","owner":{"login":"gregoil","id":29352269,"avatar_url":"https://avatars2.githubusercontent.com/u/29352269?v=4","gravatar_id":"","url":"https://api.github.com/users/gregoil","html_url":"https://github.com/gregoil","followers_url":"https://api.github.com/users/gregoil/followers","following_url":"https://api.github.com/users/gregoil/following{/other_user}","gists_url":"https://api.github.com/users/gregoil/gists{/gist_id}","starred_url":"https://api.github.com/users/gregoil/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gregoil/subscriptions","organizations_url":"https://api.github.com/users/gregoil/orgs","repos_url":"https://api.github.com/users/gregoil/repos","events_url":"https://api.github.com/users/gregoil/events{/privacy}","received_events_url":"https://api.github.com/users/gregoil/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/gregoil/rotest","description":"Resource oriented testing framework","fork":false,"url":"https://api.github.com/repos/gregoil/rotest","forks_url":"https://api.github.com/repos/gregoil/rotest/forks","keys_url":"https://api.github.com/repos/gregoil/rotest/keys{/key_id}","collaborators_url":"https://api.github.com/repos/gregoil/rotest/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/gregoil/rotest/teams","hooks_url":"https://api.github.com/repos/gregoil/rotest/hooks","issue_events_url":"https://api.github.com/repos/gregoil/rotest/issues/events{/number}","events_url":"https://api.github.com/repos/gregoil/rotest/events","assignees_url":"https://api.github.com/repos/gregoil/rotest/assignees{/user}","branches_url":"https://api.github.com/repos/gregoil/rotest/branches{/branch}","tags_url":"https://api.github.com/repos/gregoil/rotest/tags","blobs_url":"https://api.github.com/repos/gregoil/rotest/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/gregoil/rotest/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/gregoil/rotest/git/refs{/sha}","trees_url":"https://api.github.com/repos/gregoil/rotest/git/trees{/sha}","statuses_url":"https://api.github.com/repos/gregoil/rotest/statuses/{sha}","languages_url":"https://api.github.com/repos/gregoil/rotest/languages","stargazers_url":"https://api.github.com/repos/gregoil/rotest/stargazers","contributors_url":"https://api.github.com/repos/gregoil/rotest/contributors","subscribers_url":"https://api.github.com/repos/gregoil/rotest/subscribers","subscription_url":"https://api.github.com/repos/gregoil/rotest/subscription","commits_url":"https://api.github.com/repos/gregoil/rotest/commits{/sha}","git_commits_url":"https://api.github.com/repos/gregoil/rotest/git/commits{/sha}","comments_url":"https://api.github.com/repos/gregoil/rotest/comments{/number}","issue_comment_url":"https://api.github.com/repos/gregoil/rotest/issues/comments{/number}","contents_url":"https://api.github.com/repos/gregoil/rotest/contents/{+path}","compare_url":"https://api.github.com/repos/gregoil/rotest/compare/{base}...{head}","merges_url":"https://api.github.com/repos/gregoil/rotest/merges","archive_url":"https://api.github.com/repos/gregoil/rotest/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/gregoil/rotest/downloads","issues_url":"https://api.github.com/repos/gregoil/rotest/issues{/number}","pulls_url":"https://api.github.com/repos/gregoil/rotest/pulls{/number}","milestones_url":"https://api.github.com/repos/gregoil/rotest/milestones{/number}","notifications_url":"https://api.github.com/repos/gregoil/rotest/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/gregoil/rotest/labels{/name}","releases_url":"https://api.github.com/repos/gregoil/rotest/releases{/id}","deployments_url":"https://api.github.com/repos/gregoil/rotest/deployments","created_at":"2017-06-11T18:03:06Z","updated_at":"2018-03-27T18:07:08Z","pushed_at":"2018-03-28T20:23:18Z","git_url":"git://github.com/gregoil/rotest.git","ssh_url":"git@github.com:gregoil/rotest.git","clone_url":"https://github.com/gregoil/rotest.git","svn_url":"https://github.com/gregoil/rotest","homepage":null,"size":503,"stargazers_count":17,"watchers_count":17,"language":"Python","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":3,"mirror_url":null,"archived":false,"open_issues_count":8,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit"},"forks":3,"open_issues":8,"watchers":17,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/gregoil/rotest/pulls/43"},"html":{"href":"https://github.com/gregoil/rotest/pull/43"},"issue":{"href":"https://api.github.com/repos/gregoil/rotest/issues/43"},"comments":{"href":"https://api.github.com/repos/gregoil/rotest/issues/43/comments"},"review_comments":{"href":"https://api.github.com/repos/gregoil/rotest/pulls/43/comments"},"review_comment":{"href":"https://api.github.com/repos/gregoil/rotest/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/gregoil/rotest/pulls/43/commits"},"statuses":{"href":"https://api.github.com/repos/gregoil/rotest/statuses/3714060a79cf0822c39bfd4a33b9b9f807135789"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"rinslow"}}