{"action":"created","comment":{"url":"https://api.github.com/repos/MycroftAI/mycroft-core/pulls/comments/198188342","pull_request_review_id":132073372,"id":198188342,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDE5ODE4ODM0Mg==","diff_hunk":"@@ -112,116 +110,98 @@ def found_wake_word(self, frame_data):\n class PreciseHotword(HotWordEngine):\n     def __init__(self, key_phrase=\"hey mycroft\", config=None, lang=\"en-us\"):\n         super(PreciseHotword, self).__init__(key_phrase, config, lang)\n-        self.update_freq = 24  # in hours\n-\n+        from precise_runner import (\n+            PreciseRunner, PreciseEngine, ReadWriteStream\n+        )\n+        local_conf = LocalConf(USER_CONFIG)\n+        if local_conf.get('precise', {}).get('dist_url') == \\\n+                'http://bootstrap.mycroft.ai/artifacts/static/daily/':\n+            del local_conf['precise']['dist_url']\n+            local_conf.store()\n+            Configuration.updated(None)\n+\n+        self.show_download_progress = Timer(0, lambda: None)\n         precise_config = Configuration.get()['precise']\n-        self.dist_url = precise_config['dist_url']\n-        self.models_url = precise_config['models_url']\n-        self.exe_name = 'precise-stream'\n+        precise_exe = self.install_exe(precise_config['dist_url'])\n+        precise_model = self.install_model(\n+            precise_config['model_url'], key_phrase.replace(' ', '-')\n+        ).replace('.tar.gz', '.pb')\n \n-        model_name, model_path = self.get_model_info()\n-\n-        exe_file = self.find_download_exe()\n-        LOG.info('Found precise executable: ' + exe_file)\n-        self.update_model(model_name, model_path)\n-\n-        args = [exe_file, model_path, '1024']\n-        self.proc = Popen(args, stdin=PIPE, stdout=PIPE)\n         self.has_found = False\n-        self.cooldown = 20\n-        t = Thread(target=self.check_stdout)\n-        t.daemon = True\n-        t.start()\n-\n-    def get_model_info(self):\n-        ww = Configuration.get()['listener']['wake_word']\n-        model_name = ww.replace(' ', '-') + '.pb'\n-        model_folder = expanduser('~/.mycroft/precise')\n-        if not isdir(model_folder):\n-            mkdir(model_folder)\n-        model_path = join(model_folder, model_name)\n-        return model_name, model_path\n-\n-    def find_download_exe(self):\n-        try:\n-            if call('command -v ' + self.exe_name,\n-                    shell=True, stdout=PIPE) == 0:\n-                return self.exe_name\n-        except OSError:\n-            pass\n-\n-        precise_folder = expanduser('~/.mycroft/precise')\n-        if isfile(join(precise_folder, 'precise-stream')):\n-            os.remove(join(precise_folder, 'precise-stream'))\n-\n-        exe_file = join(precise_folder, 'precise-stream', 'precise-stream')\n-        if isfile(exe_file):\n-            return exe_file\n-\n-        import platform\n-        import stat\n-\n-        def snd_msg(cmd):\n-            \"\"\"Send message to faceplate\"\"\"\n-            Popen('echo \"' + cmd + '\" > /dev/ttyAMA0', shell=True)\n-\n-        arch = platform.machine()\n-\n-        url = self.dist_url + arch + '/precise-stream.tar.gz'\n-        tar_file = NamedTemporaryFile().name + '.tar.gz'\n-\n-        snd_msg('mouth.text=Updating Listener...')\n-        cur_dir = getcwd()\n-        chdir(precise_folder)\n+        self.stream = ReadWriteStream()\n+\n+        def on_activation():\n+            self.has_found = True\n+\n+        self.runner = PreciseRunner(\n+            PreciseEngine(precise_exe, precise_model),\n+            stream=self.stream, on_activation=on_activation\n+        )\n+        self.runner.start()\n+\n+    @property\n+    def folder(self):\n+        return join(expanduser('~'), '.mycroft', 'precise')\n+\n+    def install_exe(self, url: str) -> str:\n+        url = url.format(arch=platform.machine())\n+        if not url.endswith('.tar.gz'):\n+            url = requests.get(url).text.strip()\n+        if install_package(\n+                url, self.folder,\n+                on_download=self.on_download, on_complete=self.on_complete\n+        ):\n+            raise TriggerReload\n+        return join(self.folder, 'precise-engine', 'precise-engine')\n+\n+    def install_model(self, url: str, wake_word: str) -> str:\n+        model_url = url.format(wake_word=wake_word)\n+        model_file = join(self.folder, posixpath.basename(model_url))\n         try:\n-            self.download(url, tar_file)\n-            call(['tar', '-xzvf', tar_file])\n-        finally:\n-            chdir(cur_dir)\n-            snd_msg('mouth.reset')\n-\n-        if not isfile(exe_file):\n-            raise RuntimeError('Could not extract file: ' + exe_file)\n-        os.chmod(exe_file, os.stat(exe_file).st_mode | stat.S_IEXEC)\n-        return exe_file\n+            install_package(\n+                model_url, self.folder,\n+                on_download=lambda: LOG.info('Updated precise model')\n+            )\n+        except HTTPError:\n+            if isfile(model_file):\n+                LOG.info(\"Couldn't find remote model.  Using local file\")\n+            else:\n+                raise RuntimeError('Failed to download model:', model_url)\n+        return model_file\n \n     @staticmethod\n-    def download(url, filename):\n-        import shutil\n-\n-        from urllib.request import urlopen\n-        LOG.info('Downloading: ' + url)\n-        req = urlopen(url)\n-        with open(filename, 'wb') as fp:\n-            shutil.copyfileobj(req, fp)\n-        LOG.info('Download complete.')\n-\n-    def update_model(self, name, file_name):\n-        if isfile(file_name):\n-            stat = os.stat(file_name)\n-            if get_time() - stat.st_mtime < self.update_freq * 60 * 60:\n-                return\n-        name = name.replace(' ', '%20')\n-        url = self.models_url + name\n-        self.download(url, file_name)\n-        self.download(url + '.params', file_name + '.params')\n-\n-    def check_stdout(self):\n-        while True:\n-            line = self.proc.stdout.readline()\n-            if self.cooldown > 0:\n-                self.cooldown -= 1\n-                self.has_found = False\n-                continue\n-            self.has_found = float(line) > 0.5\n+    def _snd_msg(cmd):\n+        with suppress(OSError):\n+            with open('/dev/ttyAMA0', 'w') as f:\n+                print(cmd, file=f)\n+\n+    def on_download(self):\n+        LOG.info('Downloading Precise executable...')\n+        for old_package in glob(join(self.folder, 'precise-engine_*.tar.gz')):\n+            os.remove(old_package)\n+        self.show_download_progress = Timer(\n+            5, self.during_download, args=[True]\n+        )\n+        self.show_download_progress.start()\n+\n+    def during_download(self, first_run=False):\n+        LOG.info('Still downloading executable...')\n+        if first_run:\n+            self._snd_msg('mouth.text=Updating listener...')\n+        self.show_download_progress = Timer(5, self.during_download)\n+        self.show_download_progress.start()","path":"mycroft/client/speech/hotword_factory.py","position":null,"original_position":237,"commit_id":"fb260b1886ba516b838747ad15ef52afc6d03fff","original_commit_id":"7b5caf2f9c9dea0eaa3c89c3bf3e9da19a000344","user":{"login":"MatthewScholefield","id":5875019,"node_id":"MDQ6VXNlcjU4NzUwMTk=","avatar_url":"https://avatars0.githubusercontent.com/u/5875019?v=4","gravatar_id":"","url":"https://api.github.com/users/MatthewScholefield","html_url":"https://github.com/MatthewScholefield","followers_url":"https://api.github.com/users/MatthewScholefield/followers","following_url":"https://api.github.com/users/MatthewScholefield/following{/other_user}","gists_url":"https://api.github.com/users/MatthewScholefield/gists{/gist_id}","starred_url":"https://api.github.com/users/MatthewScholefield/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/MatthewScholefield/subscriptions","organizations_url":"https://api.github.com/users/MatthewScholefield/orgs","repos_url":"https://api.github.com/users/MatthewScholefield/repos","events_url":"https://api.github.com/users/MatthewScholefield/events{/privacy}","received_events_url":"https://api.github.com/users/MatthewScholefield/received_events","type":"User","site_admin":false},"body":"I can't replicate in Python 2 or 3:\r\n```python\r\nfrom __future__ import print_function\r\nfrom time import sleep\r\nfrom threading import Thread, Timer\r\ntimer = Timer(1, lambda: print('Timer ran'))\r\ntimer.start(); sleep(0.5); Thread(target=timer.cancel).start()\r\n```","created_at":"2018-06-26T15:20:50Z","updated_at":"2018-06-26T15:20:51Z","html_url":"https://github.com/MycroftAI/mycroft-core/pull/1657#discussion_r198188342","pull_request_url":"https://api.github.com/repos/MycroftAI/mycroft-core/pulls/1657","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/MycroftAI/mycroft-core/pulls/comments/198188342"},"html":{"href":"https://github.com/MycroftAI/mycroft-core/pull/1657#discussion_r198188342"},"pull_request":{"href":"https://api.github.com/repos/MycroftAI/mycroft-core/pulls/1657"}},"in_reply_to_id":198030479},"pull_request":{"url":"https://api.github.com/repos/MycroftAI/mycroft-core/pulls/1657","id":197146315,"node_id":"MDExOlB1bGxSZXF1ZXN0MTk3MTQ2MzE1","html_url":"https://github.com/MycroftAI/mycroft-core/pull/1657","diff_url":"https://github.com/MycroftAI/mycroft-core/pull/1657.diff","patch_url":"https://github.com/MycroftAI/mycroft-core/pull/1657.patch","issue_url":"https://api.github.com/repos/MycroftAI/mycroft-core/issues/1657","number":1657,"state":"open","locked":false,"title":"Refactor Precise engine and support engine timeouts","user":{"login":"MatthewScholefield","id":5875019,"node_id":"MDQ6VXNlcjU4NzUwMTk=","avatar_url":"https://avatars0.githubusercontent.com/u/5875019?v=4","gravatar_id":"","url":"https://api.github.com/users/MatthewScholefield","html_url":"https://github.com/MatthewScholefield","followers_url":"https://api.github.com/users/MatthewScholefield/followers","following_url":"https://api.github.com/users/MatthewScholefield/following{/other_user}","gists_url":"https://api.github.com/users/MatthewScholefield/gists{/gist_id}","starred_url":"https://api.github.com/users/MatthewScholefield/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/MatthewScholefield/subscriptions","organizations_url":"https://api.github.com/users/MatthewScholefield/orgs","repos_url":"https://api.github.com/users/MatthewScholefield/repos","events_url":"https://api.github.com/users/MatthewScholefield/events{/privacy}","received_events_url":"https://api.github.com/users/MatthewScholefield/received_events","type":"User","site_admin":false},"body":"## Description\r\nThis PR improves how Precise is downloaded and updated along with uses the new Precise Python API.\r\n\r\n## How to test\r\n - Make sure you can still say the wake word (via Pocketsphinx) when it updates\r\n - Make sure you can say the wake word after it updates (via Precise)\r\n - Make sure it installs properly if you delete items in `~/.mycroft/precise`\r\n","created_at":"2018-06-25T15:13:06Z","updated_at":"2018-06-26T15:20:51Z","closed_at":null,"merged_at":null,"merge_commit_sha":"32f8659204ef591cf09549549b4b361ea4524995","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":664720248,"node_id":"MDU6TGFiZWw2NjQ3MjAyNDg=","url":"https://api.github.com/repos/MycroftAI/mycroft-core/labels/CLA:%20Yes","name":"CLA: Yes","color":"0e8a16","default":false},{"id":646386270,"node_id":"MDU6TGFiZWw2NDYzODYyNzA=","url":"https://api.github.com/repos/MycroftAI/mycroft-core/labels/type:%20Code%20Improvements%20/%20Refactor","name":"type: Code Improvements / Refactor","color":"fbca04","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/MycroftAI/mycroft-core/pulls/1657/commits","review_comments_url":"https://api.github.com/repos/MycroftAI/mycroft-core/pulls/1657/comments","review_comment_url":"https://api.github.com/repos/MycroftAI/mycroft-core/pulls/comments{/number}","comments_url":"https://api.github.com/repos/MycroftAI/mycroft-core/issues/1657/comments","statuses_url":"https://api.github.com/repos/MycroftAI/mycroft-core/statuses/fb260b1886ba516b838747ad15ef52afc6d03fff","head":{"label":"MycroftAI:feature/rewrite-precise","ref":"feature/rewrite-precise","sha":"fb260b1886ba516b838747ad15ef52afc6d03fff","user":{"login":"MycroftAI","id":14171097,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE0MTcxMDk3","avatar_url":"https://avatars0.githubusercontent.com/u/14171097?v=4","gravatar_id":"","url":"https://api.github.com/users/MycroftAI","html_url":"https://github.com/MycroftAI","followers_url":"https://api.github.com/users/MycroftAI/followers","following_url":"https://api.github.com/users/MycroftAI/following{/other_user}","gists_url":"https://api.github.com/users/MycroftAI/gists{/gist_id}","starred_url":"https://api.github.com/users/MycroftAI/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/MycroftAI/subscriptions","organizations_url":"https://api.github.com/users/MycroftAI/orgs","repos_url":"https://api.github.com/users/MycroftAI/repos","events_url":"https://api.github.com/users/MycroftAI/events{/privacy}","received_events_url":"https://api.github.com/users/MycroftAI/received_events","type":"Organization","site_admin":false},"repo":{"id":59299524,"node_id":"MDEwOlJlcG9zaXRvcnk1OTI5OTUyNA==","name":"mycroft-core","full_name":"MycroftAI/mycroft-core","owner":{"login":"MycroftAI","id":14171097,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE0MTcxMDk3","avatar_url":"https://avatars0.githubusercontent.com/u/14171097?v=4","gravatar_id":"","url":"https://api.github.com/users/MycroftAI","html_url":"https://github.com/MycroftAI","followers_url":"https://api.github.com/users/MycroftAI/followers","following_url":"https://api.github.com/users/MycroftAI/following{/other_user}","gists_url":"https://api.github.com/users/MycroftAI/gists{/gist_id}","starred_url":"https://api.github.com/users/MycroftAI/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/MycroftAI/subscriptions","organizations_url":"https://api.github.com/users/MycroftAI/orgs","repos_url":"https://api.github.com/users/MycroftAI/repos","events_url":"https://api.github.com/users/MycroftAI/events{/privacy}","received_events_url":"https://api.github.com/users/MycroftAI/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/MycroftAI/mycroft-core","description":"Mycroft Core, the Mycroft Artificial Intelligence platform.","fork":false,"url":"https://api.github.com/repos/MycroftAI/mycroft-core","forks_url":"https://api.github.com/repos/MycroftAI/mycroft-core/forks","keys_url":"https://api.github.com/repos/MycroftAI/mycroft-core/keys{/key_id}","collaborators_url":"https://api.github.com/repos/MycroftAI/mycroft-core/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/MycroftAI/mycroft-core/teams","hooks_url":"https://api.github.com/repos/MycroftAI/mycroft-core/hooks","issue_events_url":"https://api.github.com/repos/MycroftAI/mycroft-core/issues/events{/number}","events_url":"https://api.github.com/repos/MycroftAI/mycroft-core/events","assignees_url":"https://api.github.com/repos/MycroftAI/mycroft-core/assignees{/user}","branches_url":"https://api.github.com/repos/MycroftAI/mycroft-core/branches{/branch}","tags_url":"https://api.github.com/repos/MycroftAI/mycroft-core/tags","blobs_url":"https://api.github.com/repos/MycroftAI/mycroft-core/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/MycroftAI/mycroft-core/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/MycroftAI/mycroft-core/git/refs{/sha}","trees_url":"https://api.github.com/repos/MycroftAI/mycroft-core/git/trees{/sha}","statuses_url":"https://api.github.com/repos/MycroftAI/mycroft-core/statuses/{sha}","languages_url":"https://api.github.com/repos/MycroftAI/mycroft-core/languages","stargazers_url":"https://api.github.com/repos/MycroftAI/mycroft-core/stargazers","contributors_url":"https://api.github.com/repos/MycroftAI/mycroft-core/contributors","subscribers_url":"https://api.github.com/repos/MycroftAI/mycroft-core/subscribers","subscription_url":"https://api.github.com/repos/MycroftAI/mycroft-core/subscription","commits_url":"https://api.github.com/repos/MycroftAI/mycroft-core/commits{/sha}","git_commits_url":"https://api.github.com/repos/MycroftAI/mycroft-core/git/commits{/sha}","comments_url":"https://api.github.com/repos/MycroftAI/mycroft-core/comments{/number}","issue_comment_url":"https://api.github.com/repos/MycroftAI/mycroft-core/issues/comments{/number}","contents_url":"https://api.github.com/repos/MycroftAI/mycroft-core/contents/{+path}","compare_url":"https://api.github.com/repos/MycroftAI/mycroft-core/compare/{base}...{head}","merges_url":"https://api.github.com/repos/MycroftAI/mycroft-core/merges","archive_url":"https://api.github.com/repos/MycroftAI/mycroft-core/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/MycroftAI/mycroft-core/downloads","issues_url":"https://api.github.com/repos/MycroftAI/mycroft-core/issues{/number}","pulls_url":"https://api.github.com/repos/MycroftAI/mycroft-core/pulls{/number}","milestones_url":"https://api.github.com/repos/MycroftAI/mycroft-core/milestones{/number}","notifications_url":"https://api.github.com/repos/MycroftAI/mycroft-core/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/MycroftAI/mycroft-core/labels{/name}","releases_url":"https://api.github.com/repos/MycroftAI/mycroft-core/releases{/id}","deployments_url":"https://api.github.com/repos/MycroftAI/mycroft-core/deployments","created_at":"2016-05-20T14:11:07Z","updated_at":"2018-06-26T12:05:19Z","pushed_at":"2018-06-26T15:14:30Z","git_url":"git://github.com/MycroftAI/mycroft-core.git","ssh_url":"git@github.com:MycroftAI/mycroft-core.git","clone_url":"https://github.com/MycroftAI/mycroft-core.git","svn_url":"https://github.com/MycroftAI/mycroft-core","homepage":"https://mycroft.ai","size":114618,"stargazers_count":2477,"watchers_count":2477,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":601,"mirror_url":null,"archived":false,"open_issues_count":193,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":601,"open_issues":193,"watchers":2477,"default_branch":"dev"}},"base":{"label":"MycroftAI:dev","ref":"dev","sha":"fa4173a2d3672c9609dde82e55571734d864fd03","user":{"login":"MycroftAI","id":14171097,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE0MTcxMDk3","avatar_url":"https://avatars0.githubusercontent.com/u/14171097?v=4","gravatar_id":"","url":"https://api.github.com/users/MycroftAI","html_url":"https://github.com/MycroftAI","followers_url":"https://api.github.com/users/MycroftAI/followers","following_url":"https://api.github.com/users/MycroftAI/following{/other_user}","gists_url":"https://api.github.com/users/MycroftAI/gists{/gist_id}","starred_url":"https://api.github.com/users/MycroftAI/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/MycroftAI/subscriptions","organizations_url":"https://api.github.com/users/MycroftAI/orgs","repos_url":"https://api.github.com/users/MycroftAI/repos","events_url":"https://api.github.com/users/MycroftAI/events{/privacy}","received_events_url":"https://api.github.com/users/MycroftAI/received_events","type":"Organization","site_admin":false},"repo":{"id":59299524,"node_id":"MDEwOlJlcG9zaXRvcnk1OTI5OTUyNA==","name":"mycroft-core","full_name":"MycroftAI/mycroft-core","owner":{"login":"MycroftAI","id":14171097,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE0MTcxMDk3","avatar_url":"https://avatars0.githubusercontent.com/u/14171097?v=4","gravatar_id":"","url":"https://api.github.com/users/MycroftAI","html_url":"https://github.com/MycroftAI","followers_url":"https://api.github.com/users/MycroftAI/followers","following_url":"https://api.github.com/users/MycroftAI/following{/other_user}","gists_url":"https://api.github.com/users/MycroftAI/gists{/gist_id}","starred_url":"https://api.github.com/users/MycroftAI/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/MycroftAI/subscriptions","organizations_url":"https://api.github.com/users/MycroftAI/orgs","repos_url":"https://api.github.com/users/MycroftAI/repos","events_url":"https://api.github.com/users/MycroftAI/events{/privacy}","received_events_url":"https://api.github.com/users/MycroftAI/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/MycroftAI/mycroft-core","description":"Mycroft Core, the Mycroft Artificial Intelligence platform.","fork":false,"url":"https://api.github.com/repos/MycroftAI/mycroft-core","forks_url":"https://api.github.com/repos/MycroftAI/mycroft-core/forks","keys_url":"https://api.github.com/repos/MycroftAI/mycroft-core/keys{/key_id}","collaborators_url":"https://api.github.com/repos/MycroftAI/mycroft-core/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/MycroftAI/mycroft-core/teams","hooks_url":"https://api.github.com/repos/MycroftAI/mycroft-core/hooks","issue_events_url":"https://api.github.com/repos/MycroftAI/mycroft-core/issues/events{/number}","events_url":"https://api.github.com/repos/MycroftAI/mycroft-core/events","assignees_url":"https://api.github.com/repos/MycroftAI/mycroft-core/assignees{/user}","branches_url":"https://api.github.com/repos/MycroftAI/mycroft-core/branches{/branch}","tags_url":"https://api.github.com/repos/MycroftAI/mycroft-core/tags","blobs_url":"https://api.github.com/repos/MycroftAI/mycroft-core/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/MycroftAI/mycroft-core/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/MycroftAI/mycroft-core/git/refs{/sha}","trees_url":"https://api.github.com/repos/MycroftAI/mycroft-core/git/trees{/sha}","statuses_url":"https://api.github.com/repos/MycroftAI/mycroft-core/statuses/{sha}","languages_url":"https://api.github.com/repos/MycroftAI/mycroft-core/languages","stargazers_url":"https://api.github.com/repos/MycroftAI/mycroft-core/stargazers","contributors_url":"https://api.github.com/repos/MycroftAI/mycroft-core/contributors","subscribers_url":"https://api.github.com/repos/MycroftAI/mycroft-core/subscribers","subscription_url":"https://api.github.com/repos/MycroftAI/mycroft-core/subscription","commits_url":"https://api.github.com/repos/MycroftAI/mycroft-core/commits{/sha}","git_commits_url":"https://api.github.com/repos/MycroftAI/mycroft-core/git/commits{/sha}","comments_url":"https://api.github.com/repos/MycroftAI/mycroft-core/comments{/number}","issue_comment_url":"https://api.github.com/repos/MycroftAI/mycroft-core/issues/comments{/number}","contents_url":"https://api.github.com/repos/MycroftAI/mycroft-core/contents/{+path}","compare_url":"https://api.github.com/repos/MycroftAI/mycroft-core/compare/{base}...{head}","merges_url":"https://api.github.com/repos/MycroftAI/mycroft-core/merges","archive_url":"https://api.github.com/repos/MycroftAI/mycroft-core/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/MycroftAI/mycroft-core/downloads","issues_url":"https://api.github.com/repos/MycroftAI/mycroft-core/issues{/number}","pulls_url":"https://api.github.com/repos/MycroftAI/mycroft-core/pulls{/number}","milestones_url":"https://api.github.com/repos/MycroftAI/mycroft-core/milestones{/number}","notifications_url":"https://api.github.com/repos/MycroftAI/mycroft-core/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/MycroftAI/mycroft-core/labels{/name}","releases_url":"https://api.github.com/repos/MycroftAI/mycroft-core/releases{/id}","deployments_url":"https://api.github.com/repos/MycroftAI/mycroft-core/deployments","created_at":"2016-05-20T14:11:07Z","updated_at":"2018-06-26T12:05:19Z","pushed_at":"2018-06-26T15:14:30Z","git_url":"git://github.com/MycroftAI/mycroft-core.git","ssh_url":"git@github.com:MycroftAI/mycroft-core.git","clone_url":"https://github.com/MycroftAI/mycroft-core.git","svn_url":"https://github.com/MycroftAI/mycroft-core","homepage":"https://mycroft.ai","size":114618,"stargazers_count":2477,"watchers_count":2477,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":601,"mirror_url":null,"archived":false,"open_issues_count":193,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":601,"open_issues":193,"watchers":2477,"default_branch":"dev"}},"_links":{"self":{"href":"https://api.github.com/repos/MycroftAI/mycroft-core/pulls/1657"},"html":{"href":"https://github.com/MycroftAI/mycroft-core/pull/1657"},"issue":{"href":"https://api.github.com/repos/MycroftAI/mycroft-core/issues/1657"},"comments":{"href":"https://api.github.com/repos/MycroftAI/mycroft-core/issues/1657/comments"},"review_comments":{"href":"https://api.github.com/repos/MycroftAI/mycroft-core/pulls/1657/comments"},"review_comment":{"href":"https://api.github.com/repos/MycroftAI/mycroft-core/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/MycroftAI/mycroft-core/pulls/1657/commits"},"statuses":{"href":"https://api.github.com/repos/MycroftAI/mycroft-core/statuses/fb260b1886ba516b838747ad15ef52afc6d03fff"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"MatthewScholefield"}}