{"action":"created","comment":{"url":"https://api.github.com/repos/shotgunsoftware/tk-core/pulls/comments/29294003","id":29294003,"diff_hunk":"@@ -0,0 +1,225 @@\n+# Copyright (c) 2015 Shotgun Software Inc.\n+#\n+# CONFIDENTIAL AND PROPRIETARY\n+#\n+# This work is provided \"AS IS\" and subject to the Shotgun Pipeline Toolkit\n+# Source Code License included in this distribution package. See LICENSE.\n+# By accessing, using, copying or modifying this work you indicate your\n+# agreement to the Shotgun Pipeline Toolkit Source Code License. All rights\n+# not expressly granted therein are reserved by Shotgun Software Inc.\n+\n+from . import interactive_authentication\n+from . import user\n+from . import user_impl\n+from . import session_cache\n+from .errors import InvalidCredentials\n+from .defaults_manager import DefaultsManager\n+\n+import logging\n+logger = logging.getLogger(\"shotgun_authentication\").getChild(\"shotgun_authenticator\")\n+\n+\n+class ShotgunAuthenticator(object):\n+    \"\"\"\n+    Shotgun Authentication\n+    ----------------------\n+\n+    This class is used to help maintain an authenticated Shotgun User session\n+    across multiple application launches and environments. By default, the\n+    library is not tied to any particular Shotgun site - you can use it to\n+    produce an authenticated user for any site of their choosing.\n+\n+    The library is essentially a series of factory methods, all returning\n+    ShotgunUser derived instances. This instance represents an established user\n+    in Shotgun. You can serialize this object and pass it around, etc. The\n+    create_sg_connection() method returns a shotgun instance based on the\n+    credentials of this user. It wraps around a Shotgun connection and traps\n+    authentication errors so that whenever the Shotgun connection has expired,\n+    it is automatically renewed by prompting the user to type in their password.\n+    Whenever QT is available, a dialog is shown to aid in this prompting.\n+\n+    If you want to customize any of the logic of how the authentication\n+    stores values, handles defaults or manages the behaviour in general,\n+    implement an DefaultsManager class and pass it to the constructor of the\n+    ShotgunAuthenticator object.\n+    \"\"\"\n+\n+    def __init__(self, defaults_manager=None):\n+        \"\"\"\n+        Constructor\n+\n+        :param defaults_manager: A DefaultsManager object that defines the basic\n+                                 behaviour of this authenticator. If omitted,\n+                                 the default, built-in DefaultsManager will be\n+                                 used.\n+        \"\"\"\n+        self._defaults_manager = defaults_manager or DefaultsManager()\n+\n+    def clear_default_user(self):\n+        \"\"\"\n+        Removes the default user's credentials from disk for the default host. The\n+        next time the ShotgunAuthenticator.get_saved_user method is called,\n+        None will be returned.\n+\n+        :returns: If a user was cleared, the user object is returned, None otherwise.\n+        \"\"\"\n+        try:\n+            user = self.create_session_user(\n+                host=self._defaults_manager.get_host(),\n+                login=self._defaults_manager.get_login(),\n+                http_proxy=self._defaults_manager.get_http_proxy()\n+            )\n+            session_cache.delete_session_data(user.host, user.login)\n+            return user\n+        except InvalidCredentials:\n+            # Not all credentials were found, so there is no default user.\n+            return None\n+\n+    def get_user_from_prompt(self):\n+        \"\"\"\n+        Display a UI prompt (QT based UI if possible but may fall back on console)\n+\n+        The DefaultsManager can be used to pre-fill the host and login name.\n+\n+        :raises AuthenticationCancelled: If the user cancels the authentication process,\n+                                         an AuthenticationCancelled is thrown.\n+\n+        :returns: The SessionUser based on the login information provided.\n+        \"\"\"\n+        host, login, session_token = interactive_authentication.authenticate(\n+            self._defaults_manager.get_host(),\n+            self._defaults_manager.get_login(),\n+            self._defaults_manager.get_http_proxy(),\n+            self._defaults_manager.is_host_fixed()\n+        )\n+        return self.create_session_user(\n+            login=login, session_token=session_token,\n+            host=host, http_proxy=self._defaults_manager.get_http_proxy()\n+        )\n+\n+    def create_session_user(self, login, session_token=None, password=None, host=None, http_proxy=None):\n+        \"\"\"\n+        Create an AuthenticatedUser given a set of human user credentials.\n+        Either a password or session token must be supplied. If a password is supplied,\n+        a session token will be generated for security reasons.\n+\n+        :param login: Shotgun user login\n+        :param session_token: Shotgun session token\n+        :param password: Shotgun password\n+        :param host: Shotgun host to log in to. If None, the default host will be used.\n+        :param http_proxy: Shotgun proxy to use. If None, the default http proxy will be used.\n+\n+        :returns: A SessionUser instance.\n+        \"\"\"\n+        # Get the defaults is arguments were None.\n+        host = host or self._defaults_manager.get_host()\n+        http_proxy = http_proxy or self._defaults_manager.get_http_proxy()\n+\n+        # Create a session user\n+        return user.ShotgunUser(\n+            user_impl.SessionUser(host, login, session_token, http_proxy, password=password)\n+        )\n+\n+    def create_script_user(self, api_script, api_key, host=None, http_proxy=None):\n+        \"\"\"\n+        Create an AuthenticatedUser given a set of script credentials.\n+\n+        :param script_user: Shotgun script user\n+        :param script_key: Shotgun script key\n+        :param host: Shotgun host to log in to. If None, the default host will\n+                     be used.\n+        :param http_proxy: Shotgun proxy to use. If None, the default http proxy\n+                           will be used.\n+\n+        :returns: A ShotgunUser derived instance.\n+        \"\"\"\n+        return user.ShotgunUser(\n+            user_impl.ScriptUser(\n+                host or self._defaults_manager.get_host(),\n+                api_script,\n+                api_key,\n+                http_proxy or self._defaults_manager.get_http_proxy(),\n+            )\n+        )\n+\n+    def get_default_host(self):\n+        \"\"\"\n+        Returns the host from the defaults manager.\n+        :returns: The default host string.\n+        \"\"\"\n+        return self._defaults_manager.get_host()\n+\n+    def get_default_http_proxy(self):\n+        \"\"\"\n+        Returns the HTTP proxy from the defaults manager.\n+        :returns: The default http proxy string.\n+        \"\"\"\n+        return self._defaults_manager.get_http_proxy()\n+\n+    def get_default_user(self):\n+        \"\"\"\n+        Returns the default user from the defaults manager.\n+        :returns: A ShotgunUser derived instance if available, None otherwise.\n+        \"\"\"\n+        # Get the credentials\n+        credentials = self._defaults_manager.get_user_credentials()","path":"python/tank_vendor/shotgun_authentication/shotgun_authenticator.py","position":165,"original_position":165,"commit_id":"6f60843d943361644b23f1b37d5825e44cf26b9a","original_commit_id":"6f60843d943361644b23f1b37d5825e44cf26b9a","user":{"login":"manneohrstrom","id":337710,"avatar_url":"https://avatars.githubusercontent.com/u/337710?v=3","gravatar_id":"","url":"https://api.github.com/users/manneohrstrom","html_url":"https://github.com/manneohrstrom","followers_url":"https://api.github.com/users/manneohrstrom/followers","following_url":"https://api.github.com/users/manneohrstrom/following{/other_user}","gists_url":"https://api.github.com/users/manneohrstrom/gists{/gist_id}","starred_url":"https://api.github.com/users/manneohrstrom/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/manneohrstrom/subscriptions","organizations_url":"https://api.github.com/users/manneohrstrom/orgs","repos_url":"https://api.github.com/users/manneohrstrom/repos","events_url":"https://api.github.com/users/manneohrstrom/events{/privacy}","received_events_url":"https://api.github.com/users/manneohrstrom/received_events","type":"User","site_admin":false},"body":"I am still not sure I understand the meaning of this `defaults_manager.get_user_credentials()` - what is the intent? Can it return different things (e.g. script credentials / user credentials)? Docstring just says\r\n\r\n```\r\n        \"\"\"\r\n        Override to provide a default user's dictionary of credentials.\r\n\r\n        :returns: Default implementation returns None.\r\n        \"\"\"\r\n```\r\n\r\nCurious about the intent here - wondering if we can tweak the form on which the data is being returned.","created_at":"2015-04-28T22:11:04Z","updated_at":"2015-04-28T22:11:04Z","html_url":"https://github.com/shotgunsoftware/tk-core/pull/147#discussion_r29294003","pull_request_url":"https://api.github.com/repos/shotgunsoftware/tk-core/pulls/147","_links":{"self":{"href":"https://api.github.com/repos/shotgunsoftware/tk-core/pulls/comments/29294003"},"html":{"href":"https://github.com/shotgunsoftware/tk-core/pull/147#discussion_r29294003"},"pull_request":{"href":"https://api.github.com/repos/shotgunsoftware/tk-core/pulls/147"}}},"pull_request":{"url":"https://api.github.com/repos/shotgunsoftware/tk-core/pulls/147","id":33076928,"html_url":"https://github.com/shotgunsoftware/tk-core/pull/147","diff_url":"https://github.com/shotgunsoftware/tk-core/pull/147.diff","patch_url":"https://github.com/shotgunsoftware/tk-core/pull/147.patch","issue_url":"https://api.github.com/repos/shotgunsoftware/tk-core/issues/147","number":147,"state":"open","locked":false,"title":"#27965 - Improved Toolkit Security","user":{"login":"manneohrstrom","id":337710,"avatar_url":"https://avatars.githubusercontent.com/u/337710?v=3","gravatar_id":"","url":"https://api.github.com/users/manneohrstrom","html_url":"https://github.com/manneohrstrom","followers_url":"https://api.github.com/users/manneohrstrom/followers","following_url":"https://api.github.com/users/manneohrstrom/following{/other_user}","gists_url":"https://api.github.com/users/manneohrstrom/gists{/gist_id}","starred_url":"https://api.github.com/users/manneohrstrom/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/manneohrstrom/subscriptions","organizations_url":"https://api.github.com/users/manneohrstrom/orgs","repos_url":"https://api.github.com/users/manneohrstrom/repos","events_url":"https://api.github.com/users/manneohrstrom/events{/privacy}","received_events_url":"https://api.github.com/users/manneohrstrom/received_events","type":"User","site_admin":false},"body":"Creating a pull request for all the security changes, mainly for CR purposes.","created_at":"2015-04-10T19:39:33Z","updated_at":"2015-04-28T22:11:04Z","closed_at":null,"merged_at":null,"merge_commit_sha":"dfb3a2dd13a0f440f1bf4b6af7e96b1cdc24a6dd","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/shotgunsoftware/tk-core/pulls/147/commits","review_comments_url":"https://api.github.com/repos/shotgunsoftware/tk-core/pulls/147/comments","review_comment_url":"https://api.github.com/repos/shotgunsoftware/tk-core/pulls/comments{/number}","comments_url":"https://api.github.com/repos/shotgunsoftware/tk-core/issues/147/comments","statuses_url":"https://api.github.com/repos/shotgunsoftware/tk-core/statuses/6f60843d943361644b23f1b37d5825e44cf26b9a","head":{"label":"shotgunsoftware:security","ref":"security","sha":"6f60843d943361644b23f1b37d5825e44cf26b9a","user":{"login":"shotgunsoftware","id":317894,"avatar_url":"https://avatars.githubusercontent.com/u/317894?v=3","gravatar_id":"","url":"https://api.github.com/users/shotgunsoftware","html_url":"https://github.com/shotgunsoftware","followers_url":"https://api.github.com/users/shotgunsoftware/followers","following_url":"https://api.github.com/users/shotgunsoftware/following{/other_user}","gists_url":"https://api.github.com/users/shotgunsoftware/gists{/gist_id}","starred_url":"https://api.github.com/users/shotgunsoftware/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shotgunsoftware/subscriptions","organizations_url":"https://api.github.com/users/shotgunsoftware/orgs","repos_url":"https://api.github.com/users/shotgunsoftware/repos","events_url":"https://api.github.com/users/shotgunsoftware/events{/privacy}","received_events_url":"https://api.github.com/users/shotgunsoftware/received_events","type":"Organization","site_admin":false},"repo":{"id":4270061,"name":"tk-core","full_name":"shotgunsoftware/tk-core","owner":{"login":"shotgunsoftware","id":317894,"avatar_url":"https://avatars.githubusercontent.com/u/317894?v=3","gravatar_id":"","url":"https://api.github.com/users/shotgunsoftware","html_url":"https://github.com/shotgunsoftware","followers_url":"https://api.github.com/users/shotgunsoftware/followers","following_url":"https://api.github.com/users/shotgunsoftware/following{/other_user}","gists_url":"https://api.github.com/users/shotgunsoftware/gists{/gist_id}","starred_url":"https://api.github.com/users/shotgunsoftware/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shotgunsoftware/subscriptions","organizations_url":"https://api.github.com/users/shotgunsoftware/orgs","repos_url":"https://api.github.com/users/shotgunsoftware/repos","events_url":"https://api.github.com/users/shotgunsoftware/events{/privacy}","received_events_url":"https://api.github.com/users/shotgunsoftware/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/shotgunsoftware/tk-core","description":"The Shotgun Pipeline Toolkit Core API","fork":false,"url":"https://api.github.com/repos/shotgunsoftware/tk-core","forks_url":"https://api.github.com/repos/shotgunsoftware/tk-core/forks","keys_url":"https://api.github.com/repos/shotgunsoftware/tk-core/keys{/key_id}","collaborators_url":"https://api.github.com/repos/shotgunsoftware/tk-core/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/shotgunsoftware/tk-core/teams","hooks_url":"https://api.github.com/repos/shotgunsoftware/tk-core/hooks","issue_events_url":"https://api.github.com/repos/shotgunsoftware/tk-core/issues/events{/number}","events_url":"https://api.github.com/repos/shotgunsoftware/tk-core/events","assignees_url":"https://api.github.com/repos/shotgunsoftware/tk-core/assignees{/user}","branches_url":"https://api.github.com/repos/shotgunsoftware/tk-core/branches{/branch}","tags_url":"https://api.github.com/repos/shotgunsoftware/tk-core/tags","blobs_url":"https://api.github.com/repos/shotgunsoftware/tk-core/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/shotgunsoftware/tk-core/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/shotgunsoftware/tk-core/git/refs{/sha}","trees_url":"https://api.github.com/repos/shotgunsoftware/tk-core/git/trees{/sha}","statuses_url":"https://api.github.com/repos/shotgunsoftware/tk-core/statuses/{sha}","languages_url":"https://api.github.com/repos/shotgunsoftware/tk-core/languages","stargazers_url":"https://api.github.com/repos/shotgunsoftware/tk-core/stargazers","contributors_url":"https://api.github.com/repos/shotgunsoftware/tk-core/contributors","subscribers_url":"https://api.github.com/repos/shotgunsoftware/tk-core/subscribers","subscription_url":"https://api.github.com/repos/shotgunsoftware/tk-core/subscription","commits_url":"https://api.github.com/repos/shotgunsoftware/tk-core/commits{/sha}","git_commits_url":"https://api.github.com/repos/shotgunsoftware/tk-core/git/commits{/sha}","comments_url":"https://api.github.com/repos/shotgunsoftware/tk-core/comments{/number}","issue_comment_url":"https://api.github.com/repos/shotgunsoftware/tk-core/issues/comments{/number}","contents_url":"https://api.github.com/repos/shotgunsoftware/tk-core/contents/{+path}","compare_url":"https://api.github.com/repos/shotgunsoftware/tk-core/compare/{base}...{head}","merges_url":"https://api.github.com/repos/shotgunsoftware/tk-core/merges","archive_url":"https://api.github.com/repos/shotgunsoftware/tk-core/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/shotgunsoftware/tk-core/downloads","issues_url":"https://api.github.com/repos/shotgunsoftware/tk-core/issues{/number}","pulls_url":"https://api.github.com/repos/shotgunsoftware/tk-core/pulls{/number}","milestones_url":"https://api.github.com/repos/shotgunsoftware/tk-core/milestones{/number}","notifications_url":"https://api.github.com/repos/shotgunsoftware/tk-core/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/shotgunsoftware/tk-core/labels{/name}","releases_url":"https://api.github.com/repos/shotgunsoftware/tk-core/releases{/id}","created_at":"2012-05-09T09:12:06Z","updated_at":"2015-04-28T14:27:41Z","pushed_at":"2015-04-28T14:27:47Z","git_url":"git://github.com/shotgunsoftware/tk-core.git","ssh_url":"git@github.com:shotgunsoftware/tk-core.git","clone_url":"https://github.com/shotgunsoftware/tk-core.git","svn_url":"https://github.com/shotgunsoftware/tk-core","homepage":"","size":42101,"stargazers_count":18,"watchers_count":18,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":11,"mirror_url":null,"open_issues_count":10,"forks":11,"open_issues":10,"watchers":18,"default_branch":"master"}},"base":{"label":"shotgunsoftware:master","ref":"master","sha":"607451b44e1a2d4715fd4f184450b20479ba2141","user":{"login":"shotgunsoftware","id":317894,"avatar_url":"https://avatars.githubusercontent.com/u/317894?v=3","gravatar_id":"","url":"https://api.github.com/users/shotgunsoftware","html_url":"https://github.com/shotgunsoftware","followers_url":"https://api.github.com/users/shotgunsoftware/followers","following_url":"https://api.github.com/users/shotgunsoftware/following{/other_user}","gists_url":"https://api.github.com/users/shotgunsoftware/gists{/gist_id}","starred_url":"https://api.github.com/users/shotgunsoftware/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shotgunsoftware/subscriptions","organizations_url":"https://api.github.com/users/shotgunsoftware/orgs","repos_url":"https://api.github.com/users/shotgunsoftware/repos","events_url":"https://api.github.com/users/shotgunsoftware/events{/privacy}","received_events_url":"https://api.github.com/users/shotgunsoftware/received_events","type":"Organization","site_admin":false},"repo":{"id":4270061,"name":"tk-core","full_name":"shotgunsoftware/tk-core","owner":{"login":"shotgunsoftware","id":317894,"avatar_url":"https://avatars.githubusercontent.com/u/317894?v=3","gravatar_id":"","url":"https://api.github.com/users/shotgunsoftware","html_url":"https://github.com/shotgunsoftware","followers_url":"https://api.github.com/users/shotgunsoftware/followers","following_url":"https://api.github.com/users/shotgunsoftware/following{/other_user}","gists_url":"https://api.github.com/users/shotgunsoftware/gists{/gist_id}","starred_url":"https://api.github.com/users/shotgunsoftware/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shotgunsoftware/subscriptions","organizations_url":"https://api.github.com/users/shotgunsoftware/orgs","repos_url":"https://api.github.com/users/shotgunsoftware/repos","events_url":"https://api.github.com/users/shotgunsoftware/events{/privacy}","received_events_url":"https://api.github.com/users/shotgunsoftware/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/shotgunsoftware/tk-core","description":"The Shotgun Pipeline Toolkit Core API","fork":false,"url":"https://api.github.com/repos/shotgunsoftware/tk-core","forks_url":"https://api.github.com/repos/shotgunsoftware/tk-core/forks","keys_url":"https://api.github.com/repos/shotgunsoftware/tk-core/keys{/key_id}","collaborators_url":"https://api.github.com/repos/shotgunsoftware/tk-core/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/shotgunsoftware/tk-core/teams","hooks_url":"https://api.github.com/repos/shotgunsoftware/tk-core/hooks","issue_events_url":"https://api.github.com/repos/shotgunsoftware/tk-core/issues/events{/number}","events_url":"https://api.github.com/repos/shotgunsoftware/tk-core/events","assignees_url":"https://api.github.com/repos/shotgunsoftware/tk-core/assignees{/user}","branches_url":"https://api.github.com/repos/shotgunsoftware/tk-core/branches{/branch}","tags_url":"https://api.github.com/repos/shotgunsoftware/tk-core/tags","blobs_url":"https://api.github.com/repos/shotgunsoftware/tk-core/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/shotgunsoftware/tk-core/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/shotgunsoftware/tk-core/git/refs{/sha}","trees_url":"https://api.github.com/repos/shotgunsoftware/tk-core/git/trees{/sha}","statuses_url":"https://api.github.com/repos/shotgunsoftware/tk-core/statuses/{sha}","languages_url":"https://api.github.com/repos/shotgunsoftware/tk-core/languages","stargazers_url":"https://api.github.com/repos/shotgunsoftware/tk-core/stargazers","contributors_url":"https://api.github.com/repos/shotgunsoftware/tk-core/contributors","subscribers_url":"https://api.github.com/repos/shotgunsoftware/tk-core/subscribers","subscription_url":"https://api.github.com/repos/shotgunsoftware/tk-core/subscription","commits_url":"https://api.github.com/repos/shotgunsoftware/tk-core/commits{/sha}","git_commits_url":"https://api.github.com/repos/shotgunsoftware/tk-core/git/commits{/sha}","comments_url":"https://api.github.com/repos/shotgunsoftware/tk-core/comments{/number}","issue_comment_url":"https://api.github.com/repos/shotgunsoftware/tk-core/issues/comments{/number}","contents_url":"https://api.github.com/repos/shotgunsoftware/tk-core/contents/{+path}","compare_url":"https://api.github.com/repos/shotgunsoftware/tk-core/compare/{base}...{head}","merges_url":"https://api.github.com/repos/shotgunsoftware/tk-core/merges","archive_url":"https://api.github.com/repos/shotgunsoftware/tk-core/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/shotgunsoftware/tk-core/downloads","issues_url":"https://api.github.com/repos/shotgunsoftware/tk-core/issues{/number}","pulls_url":"https://api.github.com/repos/shotgunsoftware/tk-core/pulls{/number}","milestones_url":"https://api.github.com/repos/shotgunsoftware/tk-core/milestones{/number}","notifications_url":"https://api.github.com/repos/shotgunsoftware/tk-core/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/shotgunsoftware/tk-core/labels{/name}","releases_url":"https://api.github.com/repos/shotgunsoftware/tk-core/releases{/id}","created_at":"2012-05-09T09:12:06Z","updated_at":"2015-04-28T14:27:41Z","pushed_at":"2015-04-28T14:27:47Z","git_url":"git://github.com/shotgunsoftware/tk-core.git","ssh_url":"git@github.com:shotgunsoftware/tk-core.git","clone_url":"https://github.com/shotgunsoftware/tk-core.git","svn_url":"https://github.com/shotgunsoftware/tk-core","homepage":"","size":42101,"stargazers_count":18,"watchers_count":18,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":11,"mirror_url":null,"open_issues_count":10,"forks":11,"open_issues":10,"watchers":18,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/shotgunsoftware/tk-core/pulls/147"},"html":{"href":"https://github.com/shotgunsoftware/tk-core/pull/147"},"issue":{"href":"https://api.github.com/repos/shotgunsoftware/tk-core/issues/147"},"comments":{"href":"https://api.github.com/repos/shotgunsoftware/tk-core/issues/147/comments"},"review_comments":{"href":"https://api.github.com/repos/shotgunsoftware/tk-core/pulls/147/comments"},"review_comment":{"href":"https://api.github.com/repos/shotgunsoftware/tk-core/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/shotgunsoftware/tk-core/pulls/147/commits"},"statuses":{"href":"https://api.github.com/repos/shotgunsoftware/tk-core/statuses/6f60843d943361644b23f1b37d5825e44cf26b9a"}}}}