Пример #1
0
def create_sg_connection(user="******"):
    """
    Creates a standard tank shotgun connection.
    
    Note! This method returns *a brand new sg API instance*. It is slow.
    Always consider using tk.shotgun and if you don't have a tk instance,
    consider using get_sg_connection(). 
    
    Whenever a Shotgun API instance is created, it pings the server to check that 
    it is running the right versions etc. This is slow and inefficient and means that
    there will be a delay every time create_sg_connection is called.
    
    :param user: Optional shotgun config user to use when connecting to shotgun,
                 as defined in shotgun.yml. This is a deprecated flag and should not
                 be used.
    :returns: SG API instance
    """

    # Avoids cyclic imports.
    from ... import api
    sg_user = api.get_authenticated_user()

    # If there is no user, that's probably because we're running in an old script that doesn't use
    # the authenticated user concept. In that case, we'll do what we've always been doing in the
    # past, which is read shotgun.yml and expect there to be a script user.
    if sg_user is None:
        log.debug(
            "This tk session has no associated authenticated user. Falling back to "
            "creating a shotgun API instance based on script based credentials in the "
            "shotgun.yml configuration file.")

        # try to find the shotgun.yml path
        try:
            config_file_path = __get_sg_config()
        except TankError, e:
            log.error(
                "Trying to create a shotgun connection but this tk session does not have "
                "an associated authenticated user. Therefore attempted to fall back on "
                "a legacy authentication method where script based credentials are "
                "located in a file relative to the location of the core API code. This "
                "lookup in turn failed. No credentials can be determined and no connection "
                "to Shotgun can be made. Details: %s" % e)
            raise TankError(
                "Cannot connect to Shotgun - this tk session does not have "
                "an associated user and attempts to determine a valid shotgun "
                "via legacy configuration files failed. Details: %s" % e)

        log.debug("Creating shotgun connection based on details in %s" %
                  config_file_path)
        config_data = __get_sg_config_data_with_script_user(
            config_file_path, user)

        # Credentials were passed in, so let's run the legacy authentication
        # mechanism for script user.
        api_handle = shotgun_api3.Shotgun(
            config_data["host"],
            script_name=config_data["api_script"],
            api_key=config_data["api_key"],
            http_proxy=config_data.get("http_proxy"),
            connect=False)
Пример #2
0
def __create_sg_connection(config_data=None, user=None):
    """
    Creates a standard Toolkit shotgun connection.

    :param config_data: Configuration data dictionary. Keys host, api_script and api_key are
                        expected, while http_proxy is optional. If None, the user parameter will be
                        used to determine which credentials to use.
    :param user: Shotgun user from the shotgun_authentication module to use to create the
                 connection. Won't be used if config_data is set. Can be None.

    :raises TankError: Raised if both config_data and user are None.

    :returns: A Shotgun connection.
    """

    if config_data:
        # Credentials were passed in, so let's run the legacy authentication
        # mechanism for script user.
        sg = shotgun_api3.Shotgun(config_data["host"],
                                  script_name=config_data["api_script"],
                                  api_key=config_data["api_key"],
                                  http_proxy=config_data.get("http_proxy"))
    elif user:
        sg = user.create_sg_connection()
    else:
        raise TankError("No Shotgun user available.")

    # bolt on our custom user agent manager
    sg.tk_user_agent_handler = ToolkitUserAgentHandler(sg)

    return sg
Пример #3
0
def _get_site_infos(url, http_proxy=None):
    """
    Get and cache the desired site infos.

    We want this method to fail as quickly as possible if there are any
    issues. Failure is not considered critical, thus known exceptions are
    silently ignored. At the moment this method is only used to make the
    GUI show/hide some of the input fields.

    :param url:            Url of the site to query.
    :param http_proxy:     HTTP proxy to use, if any.

    :returns:   A dictionary with the site infos.
    """
    infos = {}
    try:
        # Temporary shotgun instance, used only for the purpose of checking
        # the site infos.
        #
        # The constructor of Shotgun requires either a username/login or
        # key/scriptname pair or a session_token. The token is only used in
        # calls which need to be authenticated. The 'info' call does not
        # require authentication.
        http_proxy = _sanitize_http_proxy(http_proxy).netloc
        if http_proxy:
            get_logger().debug(
                "Using HTTP proxy to connect to the Shotgun server: %s",
                http_proxy)
        # Checks if the information is in the cache, is missing or out of date.
        if url not in INFOS_CACHE or (
            (time.time() - INFOS_CACHE[url][0]) > INFOS_CACHE_TIMEOUT):
            get_logger().info("Infos for site '%s' not in cache or expired",
                              url)
            sg = shotgun_api3.Shotgun(url,
                                      session_token="dummy",
                                      connect=False,
                                      http_proxy=http_proxy)
            # Remove delay between attempts at getting the site info.  Since
            # this is called in situations where blocking during multiple
            # attempts can make UIs less responsive, we'll avoid sleeping.
            # This change was introduced after delayed retries were added in
            # python-api v3.0.41
            sg.config.rpc_attempt_interval = 0
            infos = sg.info()
            INFOS_CACHE[url] = (time.time(), infos)
        else:
            get_logger().info("Infos for site '%s' found in cache", url)
            infos = INFOS_CACHE[url][1]
    # pylint: disable=broad-except
    except Exception as exc:
        # Silently ignore exceptions
        get_logger().debug("Unable to connect with %s, got exception '%s'",
                           url, exc)

    return infos
def _get_site_infos(url, http_proxy=None):
    """
    Get and cache the desired site infos.

    We want this method to fail as quickly as possible if there are any
    issues. Failure is not considered critical, thus known exceptions are
    silently ignored. At the moment this method is only used to make the
    GUI show/hide some of the input fields.

    :param url:            Url of the site to query.
    :param http_proxy:     HTTP proxy to use, if any.

    :returns:   A dictionary with the site infos.
    """
    infos = {}
    try:
        # Temporary shotgun instance, used only for the purpose of checking
        # the site infos.
        #
        # The constructor of Shotgun requires either a username/login or
        # key/scriptname pair or a session_token. The token is only used in
        # calls which need to be authenticated. The 'info' call does not
        # require authentication.
        http_proxy = _sanitize_http_proxy(http_proxy).netloc
        if http_proxy:
            get_logger().debug(
                "Using HTTP proxy to connect to the Shotgun server: %s", http_proxy
            )
        # Checks if the information is in the cache, is missing or out of date.
        if url not in INFOS_CACHE or ((time.time() - INFOS_CACHE[url][0]) > INFOS_CACHE_TIMEOUT):
            get_logger().info("Infos for site '%s' not in cache or expired", url)
            infos = shotgun_api3.Shotgun(
                url,
                session_token="dummy",
                connect=False,
                http_proxy=http_proxy
            ).info()
            INFOS_CACHE[url] = (time.time(), infos)
        else:
            get_logger().info("Infos for site '%s' found in cache", url)
            infos = INFOS_CACHE[url][1]
    except Exception as e:
        # Silently ignore exceptions
        get_logger().debug("Unable to connect with %s, got exception '%s'", url, e)

    return infos
Пример #5
0
def __create_sg_connection(config_data=None, user=None):
    """
    Creates a standard Toolkit shotgun connection.

    :param config_data: Configuration data dictionary. Keys host, api_script and api_key are
                        expected, while http_proxy is optional. If None, the user parameter will be
                        used to determine which credentials to use.
    :param user: Shotgun user from the shotgun_authentication module to use to create the
                 connection. Won't be used if config_data is set. Can be None.

    :raises TankError: Raised if both config_data and user are None.

    :returns: A Shotgun connection.
    """

    if config_data:
        # Credentials were passed in, so let's run the legacy authentication
        # mechanism for script user.
        sg = shotgun_api3.Shotgun(config_data["host"],
                                  script_name=config_data["api_script"],
                                  api_key=config_data["api_key"],
                                  http_proxy=config_data.get("http_proxy"),
                                  connect=config_data.get("connect", True))

        if "timeout_secs" in config_data:
            sg.config.timeout_secs = config_data.get("timeout_secs")
            # The timeout can't be set until after the sg instance is created (when it has already
            # stored the timeout setting in the connection). We have to force it to re-spawn
            # the connection with the new timeout settings. It will create a new conneciton
            # automatically the next time it's called. There shouldn't be a connection yet, but
            # if there is, let's close it just in case.
            sg.close()
    elif user:
        sg = user.create_sg_connection()
    else:
        raise TankError("No Shotgun user available.")

    # bolt on our custom user agent manager
    sg.tk_user_agent_handler = ToolkitUserAgentHandler(sg)

    return sg
Пример #6
0
# not expressly granted therein are reserved by Shotgun Software Inc.

import sgtk
import os
import sys
import threading
#
# by importing QT from sgtk rather than directly, we ensure that
# the code will be compatible with both PySide and PyQt.
from sgtk.platform.qt import QtCore, QtGui

from .ui.dialog import Ui_Dialog

from tank_vendor import shotgun_api3

sg = shotgun_api3.Shotgun("https://legend.shotgunstudio.com", script_name="toolkit",
                          api_key="d0211b3fecd9b4f0141545e7fd07965a5331eee13842700f1b6477ecffba5977")
import logging
from os import walk
import csv
from pprint import PrettyPrinter

logger = sgtk.platform.get_logger(__name__)
import random
import string
import tempfile


def show_dialog(app_instance):
    """
    Shows the main dialog window.
    """
Пример #7
0
    def __create_sg_app_store_connection(self):
        """
        Creates a shotgun connection that can be used to access the Toolkit app store.

        :returns: (sg, dict) where the first item is the shotgun api instance and the second
                  is an sg entity dictionary (keys type/id) corresponding to to the user used
                  to connect to the app store.
        """
        # maintain a cache for performance
        # cache is keyed by client shotgun site
        # this assumes that there is a strict
        # 1:1 relationship between app store accounts
        # and shotgun sites.
        sg_url = self._sg_connection.base_url

        if sg_url not in self._app_store_connections:

            # Connect to associated Shotgun site and retrieve the credentials to use to
            # connect to the app store site
            try:
                (script_name,
                 script_key) = self.__get_app_store_key_from_shotgun()
            except urllib2.HTTPError, e:
                if e.code == 403:
                    # edge case alert!
                    # this is likely because our session token in shotgun has expired.
                    # The authentication system is based around wrapping the shotgun API,
                    # and requesting authentication if needed. Because the app store
                    # credentials is a separate endpoint and doesn't go via the shotgun
                    # API, we have to explicitly check.
                    #
                    # trigger a refresh of our session token by issuing a shotgun API call
                    self._sg_connection.find_one("HumanUser", [])
                    # and retry
                    (script_name,
                     script_key) = self.__get_app_store_key_from_shotgun()
                else:
                    raise

            log.debug("Connecting to %s..." % constants.SGTK_APP_STORE)
            # Connect to the app store and resolve the script user id we are connecting with.
            # Set the timeout explicitly so we ensure the connection won't hang in cases where
            # a response is not returned in a reasonable amount of time.
            app_store_sg = shotgun_api3.Shotgun(
                constants.SGTK_APP_STORE,
                script_name=script_name,
                api_key=script_key,
                http_proxy=self.__get_app_store_proxy_setting(),
                connect=False)
            # set the default timeout for app store connections
            app_store_sg.config.timeout_secs = constants.SGTK_APP_STORE_CONN_TIMEOUT

            # determine the script user running currently
            # get the API script user ID from shotgun
            try:
                script_user = app_store_sg.find_one(
                    "ApiUser",
                    filters=[["firstname", "is", script_name]],
                    fields=["type", "id"])
            except shotgun_api3.AuthenticationFault:
                raise InvalidAppStoreCredentialsError(
                    "The Toolkit App Store credentials found in Shotgun are invalid.\n"
                    "Please contact %s to resolve this issue." % SUPPORT_EMAIL)
            # Connection errors can occur for a variety of reasons. For example, there is no
            # internet access or there is a proxy server blocking access to the Toolkit app store.
            except (httplib2.HttpLib2Error, httplib2.socks.HTTPError,
                    httplib.HTTPException), e:
                raise TankAppStoreConnectionError(e)
Пример #8
0
    def __create_sg_app_store_connection(self):
        """
        Creates a shotgun connection that can be used to access the Toolkit app store.

        :returns: (sg, dict) where the first item is the shotgun api instance and the second
                  is an sg entity dictionary (keys type/id) corresponding to to the user used
                  to connect to the app store.
        """
        # maintain a cache for performance
        # cache is keyed by client shotgun site
        # this assumes that there is a strict
        # 1:1 relationship between app store accounts
        # and shotgun sites.

        if os.environ.get(constants.DISABLE_APPSTORE_ACCESS_ENV_VAR, "0") == "1":
            message = (
                "The '%s' environment variable is active, preventing connection to app store."
                % constants.DISABLE_APPSTORE_ACCESS_ENV_VAR
            )
            log.debug(message)
            raise TankAppStoreConnectionError(message)

        sg_url = self._sg_connection.base_url

        if sg_url not in self._app_store_connections:

            # Connect to associated Shotgun site and retrieve the credentials to use to
            # connect to the app store site
            try:
                (script_name, script_key) = self.__get_app_store_key_from_shotgun()
            except urllib.error.HTTPError as e:
                if e.code == 403:
                    # edge case alert!
                    # this is likely because our session token in shotgun has expired.
                    # The authentication system is based around wrapping the shotgun API,
                    # and requesting authentication if needed. Because the app store
                    # credentials is a separate endpoint and doesn't go via the shotgun
                    # API, we have to explicitly check.
                    #
                    # trigger a refresh of our session token by issuing a shotgun API call
                    self._sg_connection.find_one("HumanUser", [])
                    # and retry
                    (script_name, script_key) = self.__get_app_store_key_from_shotgun()
                else:
                    raise

            app_store = os.environ.get("SGTK_APP_STORE", constants.SGTK_APP_STORE)

            log.debug("Connecting to %s..." % app_store)
            # Connect to the app store and resolve the script user id we are connecting with.
            # Set the timeout explicitly so we ensure the connection won't hang in cases where
            # a response is not returned in a reasonable amount of time.
            app_store_sg = shotgun_api3.Shotgun(
                app_store,
                script_name=script_name,
                api_key=script_key,
                http_proxy=self.__get_app_store_proxy_setting(),
                connect=False,
            )
            # set the default timeout for app store connections
            app_store_sg.config.timeout_secs = constants.SGTK_APP_STORE_CONN_TIMEOUT

            # determine the script user running currently
            # get the API script user ID from shotgun
            try:
                script_user = app_store_sg.find_one(
                    "ApiUser",
                    filters=[["firstname", "is", script_name]],
                    fields=["type", "id"],
                )
            except shotgun_api3.AuthenticationFault:
                raise InvalidAppStoreCredentialsError(
                    "The Toolkit App Store credentials found in Shotgun are invalid.\n"
                    "Please contact support at %s to resolve this issue." % SUPPORT_URL
                )
            # Connection errors can occur for a variety of reasons. For example, there is no
            # internet access or there is a proxy server blocking access to the Toolkit app store.
            except (
                httplib2.HttpLib2Error,
                httplib2.socks.HTTPError,
                http_client.HTTPException,
            ) as e:
                raise TankAppStoreConnectionError(e)
            # In cases where there is a firewall/proxy blocking access to the app store, sometimes
            # the firewall will drop the connection instead of rejecting it. The API request will
            # timeout which unfortunately results in a generic SSLError with only the message text
            # to give us a clue why the request failed.
            # The exception raised in this case is "ssl.SSLError: The read operation timed out"
            except httplib2.ssl.SSLError as e:
                if "timed" in e.message:
                    raise TankAppStoreConnectionError(
                        "Connection to %s timed out: %s"
                        % (app_store_sg.config.server, e)
                    )
                else:
                    # other type of ssl error
                    raise TankAppStoreError(e)
            except Exception as e:
                raise TankAppStoreError(e)

            if script_user is None:
                raise TankAppStoreError(
                    "Could not evaluate the current App Store User! Please contact support."
                )

            self._app_store_connections[sg_url] = (app_store_sg, script_user)

        return self._app_store_connections[sg_url]