示例#1
0
    def test_login_to_login_authentication(self):
        """
        Ensure the configuration will always pick the user passed in when there is no script user
        in the project configuration.
        """
        default_user = self._create_session_user("default_user")

        configuration = Configuration(None, None)

        # Create a default user.
        with patch(
            "tank.authentication.ShotgunAuthenticator.get_default_user",
            return_value=default_user
        ):
            current_user = self._create_session_user("current_user")
            configuration._set_authenticated_user(
                current_user,
                current_user.login,
                sgtk.authentication.serialize_user(current_user)
            )

            # we should be using the same login...
            self.assertEqual(sgtk.get_authenticated_user().login, current_user.login)
            # ... but we shouldn't be using the name ShotgunUser instance. It should
            # have been serialized and deserialized.
            self.assertNotEqual(id(sgtk.get_authenticated_user()), id(current_user))
示例#2
0
    def test_fail_reinstantiating(self):
        """
        Ensure the configuration will recover if the user can't be serialized/unserialized.
        """
        configuration = Configuration(None, None)

        default_user = self._create_session_user("default_user")

        # Create a default user.
        with patch(
            "tank.authentication.ShotgunAuthenticator.get_default_user",
            return_value=default_user
        ):
            # Python 2.6 doesn't support multi-expression with statement, so nest the calls instead.
            with patch(
                "tank_vendor.shotgun_authentication.deserialize_user",
                wraps=tank_vendor.shotgun_authentication.deserialize_user
            ) as deserialize_wrapper:
                current_user = self._create_session_user("current_user")
                configuration._set_authenticated_user(current_user, current_user.login, "invalid")

                deserialize_wrapper.assert_called_once_with("invalid")

                # Because we couldn't unserialize, we should just get the same login...
                self.assertEqual(sgtk.get_authenticated_user().login, current_user.login)
                # ... and the original ShotgunUser back.
                self.assertEqual(id(sgtk.get_authenticated_user()), id(current_user))
示例#3
0
    def test_script_to_noscript_authentication(self):
        """
        Ensure that bootstrapping with a script into a project without a script user in its
        configuration will pick the bootstrap user.
        """
        configuration = Configuration(None, None)

        user_for_bootstrap = self._create_script_user("api_script_for_bootstrap")
        user_for_project = self._create_session_user("project_user")

        # Create a default user.
        with patch(
            "tank.authentication.ShotgunAuthenticator.get_default_user",
            return_value=user_for_project
        ):
            configuration._set_authenticated_user(
                user_for_bootstrap,
                user_for_bootstrap.login,
                sgtk.authentication.serialize_user(user_for_bootstrap)
            )

            # we should be using the same login...
            auth_user = sgtk.get_authenticated_user()
            self.assertIsNone(auth_user.login)
            self.assertEqual(auth_user.login, user_for_bootstrap.login)
            self.assertEqual(auth_user.impl.get_script(), user_for_bootstrap.impl.get_script())
            # ... but we shouldn't be using the name ShotgunUser instance. It should
            # have been serialized and deserialized.
            self.assertNotEqual(id(auth_user), id(user_for_bootstrap))
示例#4
0
    def test_login_based_authentication(self):
        """
        Ensure the configuration will always pick the user passed in when there is no script user.
        """
        configuration = Configuration(None, None)

        self._mock_default_user.login = "******"

        user = MagicMock(login="******")
        configuration._set_authenticated_user(user)

        self.assertEqual(sgtk.get_authenticated_user(), user)
def get_cache_path(identifier_dict):
    """
    Create a file name given a dictionary of identifiers,
    e.g. ``{shot: 123, project: 345}`` etc. A hash value will
    be computed based on the identifier and used to determine
    the path. The current user will be added to the hash in
    order to make it user-centric.

    If the hash key 'prefix' is detected, this will be added
    to the path as a parent folder to the cache file. This provides
    a simple way to organize different caches into different folders.

    :param dict identifier_dict: Dictionary of identifying data.
    :retuns: path on disk, relative to the current bundle's cache location.
    """
    params_hash = hashlib.md5()
    for (k, v) in identifier_dict.iteritems():
        params_hash.update(str(k))
        params_hash.update(str(v))

    # add current user to hash
    user = sgtk.get_authenticated_user()
    if user and user.login:
        params_hash.update(user.login)

    cache_location = sgtk.platform.current_bundle().cache_location

    if FOLDER_PREFIX_KEY in identifier_dict:
        # if FOLDER_PREFIX_KEY is found in the hash,
        # this will be added as a folder to the path
        data_cache_path = os.path.join(
            cache_location,
            "external_cfg",
            identifier_dict[FOLDER_PREFIX_KEY],
            "%s.pkl" % params_hash.hexdigest()
        )
    else:
        data_cache_path = os.path.join(
            cache_location,
            "external_cfg",
            "%s.pkl" % params_hash.hexdigest()
        )

    logger.debug(
        "Resolved cache path for %s to %s" % (identifier_dict, data_cache_path)
    )
    return data_cache_path
示例#6
0
    def test_endpoint_url_swap(self):
        """
        Make sure that if the endpoint changes after the bootstrap that we're using the new endpoint.
        """
        configuration = Configuration(None, None)
        bootstrap_user = self._create_session_user("default_user")
        project_user = self._create_session_user("default_user", "https://test-2.shotgunstudio.com")

        with patch(
            "tank.authentication.ShotgunAuthenticator.get_default_user",
            return_value=project_user
        ):
            configuration._set_authenticated_user(
                bootstrap_user,
                bootstrap_user.login,
                sgtk.authentication.serialize_user(bootstrap_user)
            )

        self.assertEqual(sgtk.get_authenticated_user().host, "https://test-2.shotgunstudio.com")
示例#7
0
    def test_script_to_script_authentication(self):
        """
        Ensure a project configuration overrides a script user used for bootstrapping.
        """
        configuration = Configuration(None, None)

        script_user_for_bootstrap = self._create_script_user("api_script_for_bootstrap")
        script_user_for_project = self._create_script_user("api_script_for_project")

        # Create a default user.
        with patch(
            "tank.authentication.ShotgunAuthenticator.get_default_user",
            return_value=script_user_for_project
        ):
            configuration._set_authenticated_user(
                script_user_for_bootstrap,
                script_user_for_bootstrap.login,
                sgtk.authentication.serialize_user(script_user_for_bootstrap)
            )

            # The ShotgunUser instance from get_authenticated_user was retrieved
            # through get_default_user, so we simply need to compare the object ids.
            self.assertEqual(id(sgtk.get_authenticated_user()), id(script_user_for_project))
示例#8
0
    def test_endpoint_url_swap(self):
        """
        Make sure that if the endpoint changes after the bootstrap that we're using the new endpoint.
        """
        configuration = Configuration(None, None)
        bootstrap_user = self._create_session_user("default_user")
        project_user = self._create_session_user(
            "default_user", "https://test-2.shotgunstudio.com"
        )

        with patch(
            "tank.authentication.ShotgunAuthenticator.get_default_user",
            return_value=project_user,
        ):
            configuration._set_authenticated_user(
                bootstrap_user,
                bootstrap_user.login,
                sgtk.authentication.serialize_user(bootstrap_user),
            )

        self.assertEqual(
            sgtk.get_authenticated_user().host, "https://test-2.shotgunstudio.com"
        )
示例#9
0
    def test_script_to_script_authentication(self):
        """
        Ensure a project configuration overrides a script user used for bootstrapping.
        """
        configuration = Configuration(None, None)

        script_user_for_bootstrap = self._create_script_user("api_script_for_bootstrap")
        script_user_for_project = self._create_script_user("api_script_for_project")

        # Create a default user.
        with patch(
            "tank.authentication.ShotgunAuthenticator.get_default_user",
            return_value=script_user_for_project
        ):
            configuration._set_authenticated_user(
                script_user_for_bootstrap,
                script_user_for_bootstrap.login,
                sgtk.authentication.serialize_user(script_user_for_bootstrap)
            )

            # The ShotgunUser instance from get_authenticated_user was retrieved
            # through get_default_user, so we simply need to compare the object ids.
            self.assertEqual(id(sgtk.get_authenticated_user()), id(script_user_for_project))
示例#10
0
    def test_login_to_script_authentication(self):
        """
        Ensure the configuration will always pick the script user when project configuration has
        one.
        """
        configuration = Configuration(None, None)

        script_user = self._create_script_user("api_script")

        # Create a default user.
        with patch(
            "tank.authentication.ShotgunAuthenticator.get_default_user",
            return_value=script_user
        ):
            current_user = self._create_session_user("current_user")
            configuration._set_authenticated_user(
                current_user,
                current_user.login,
                sgtk.authentication.serialize_user(current_user)
            )

            # The ShotgunUser instance from get_authenticated_user was retrieved
            # through get_default_user, so we simply need to compare the object ids.
            self.assertEqual(id(sgtk.get_authenticated_user()), id(script_user))
示例#11
0
    def setUp(self, parameters=None):
        """
        Sets up a Shotgun Mockgun instance with a project and a basic project scaffold on
        disk.

        :param parameters: Dictionary with additional parameters to control the setup.
                           The method currently supports the following parameters:

                           - 'project_tank_name': 'name' - Set the tank_name of the project to
                                                  something explicit. If not specified, this
                                                  will default to 'project_code'

                           - 'mockgun_schema_path': '/path/to/file' - Pass a specific schema to use with mockgun.
                                                    If not specified, the tk-core fixture schema
                                                    will be used.

                           - 'mockgun_schema_entity_path': '/path/to/file' - Pass a specific entity schema to use with
                                                           mockgun. If not specified, the tk-core fixture schema
                                                           will be used.
                           - 'primary_root_name': 'name' - Set the primary root name, default to 'unit_tests'.


        """
        self.addCleanup(self._assert_teardown_called)
        # Override SHOTGUN_HOME so that unit tests can be sandboxed.
        self._old_shotgun_home = os.environ.get(self.SHOTGUN_HOME)
        os.environ[self.SHOTGUN_HOME] = TANK_TEMP

        # Make sure the global settings instance has been reset so anything from a previous test doesn't
        # leak into the next one.
        UserSettings.clear_singleton()

        parameters = parameters or {}

        self._do_io = parameters.get("do_io", True)

        if "project_tank_name" in parameters:
            project_tank_name = parameters["project_tank_name"]
        else:
            # default project name
            project_tank_name = "project_code"

        # now figure out mockgun location
        # 1. see if we have it explicitly specified in the parameters
        # 2. if not, check if the fixtures location has a mockgun folder
        # 3. if not, fall back on built in mockgun fixtures

        if "mockgun_schema_path" in parameters:
            mockgun_schema_path = parameters["mockgun_schema_path"]

        elif os.path.exists(os.path.join(self.fixtures_root, "mockgun")):
            mockgun_schema_path = os.path.join(
                self.fixtures_root,
                "mockgun",
                "schema.pickle"
            )

        else:
            # use the std core fixtures
            mockgun_schema_path = os.path.join(
                self.tank_source_path,
                "tests",
                "fixtures",
                "mockgun",
                "schema.pickle"
            )

        if "mockgun_schema_entity_path" in parameters:
            mockgun_schema_entity_path = parameters["mockgun_schema_entity_path"]

        elif os.path.exists(os.path.join(self.fixtures_root, "mockgun")):
            mockgun_schema_entity_path = os.path.join(
                self.fixtures_root,
                "mockgun",
                "schema_entity.pickle"
            )

        else:
            # use the std core fixtures
            mockgun_schema_entity_path = os.path.join(
                self.tank_source_path,
                "tests",
                "fixtures",
                "mockgun",
                "schema_entity.pickle"
            )

        # The name to use for our primary storage
        self.primary_root_name = parameters.get("primary_root_name", "unit_tests")

        # set up mockgun to use our schema
        mockgun.Shotgun.set_schema_paths(mockgun_schema_path, mockgun_schema_entity_path)

        self.tank_temp = TANK_TEMP

        self.cache_root = os.path.join(self.tank_temp, "cache_root")

        # Mock this so that authentication manager works even tough we are not in a config.
        # If we don't mock it than the path cache calling get_current_user will fail.
        self._mock_return_value(
            "tank.util.shotgun.connection.get_associated_sg_config_data",
            {"host": "https://somewhere.shotgunstudio.com"}
        )

        # define entity for test project
        self.project = {
            "type": "Project",
            "id": 1,
            "tank_name": project_tank_name,
            "name": "project_name",
            "archived": False,
        }

        self.project_root = os.path.join(self.tank_temp, self.project["tank_name"].replace("/", os.path.sep))

        self.pipeline_config_root = os.path.join(self.tank_temp, "pipeline_configuration")

        if self._do_io:
            # move away previous data
            self._move_project_data()

            # create new structure
            os.makedirs(self.project_root)
            os.makedirs(self.pipeline_config_root)

            # # copy tank util scripts
            shutil.copy(
                os.path.join(self.tank_source_path, "setup", "root_binaries", "tank"),
                os.path.join(self.pipeline_config_root, "tank")
            )
            shutil.copy(
                os.path.join(self.tank_source_path, "setup", "root_binaries", "tank.bat"),
                os.path.join(self.pipeline_config_root, "tank.bat")
            )

        # project level config directories
        self.project_config = os.path.join(self.pipeline_config_root, "config")

        # create project cache directory
        project_cache_dir = os.path.join(self.pipeline_config_root, "cache")
        if self._do_io:
            os.mkdir(project_cache_dir)

        # define entity for pipeline configuration
        self.sg_pc_entity = {"type": "PipelineConfiguration",
                             "code": "Primary",
                             "id": 123,
                             "project": self.project,
                             "windows_path": self.pipeline_config_root,
                             "mac_path": self.pipeline_config_root,
                             "linux_path": self.pipeline_config_root}

        # add files needed by the pipeline config
        pc_yml = os.path.join(self.pipeline_config_root, "config", "core", "pipeline_configuration.yml")
        pc_yml_data = ("{ project_name: %s, use_shotgun_path_cache: true, pc_id: %d, "
                       "project_id: %d, pc_name: %s}\n\n" % (self.project["tank_name"],
                                                             self.sg_pc_entity["id"],
                                                             self.project["id"],
                                                             self.sg_pc_entity["code"]))
        if self._do_io:
            self.create_file(pc_yml, pc_yml_data)

        loc_yml = os.path.join(self.pipeline_config_root, "config", "core", "install_location.yml")
        loc_yml_data = "Windows: '%s'\nDarwin: '%s'\nLinux: '%s'" % (
            self.pipeline_config_root, self.pipeline_config_root, self.pipeline_config_root
        )
        if self._do_io:
            self.create_file(loc_yml, loc_yml_data)

        # inject this file which toolkit is probing for to determine
        # if an installation has been localized.
        localize_token_file = os.path.join(self.pipeline_config_root, "install", "core", "_core_upgrader.py")
        if self._do_io:
            self.create_file(localize_token_file, "foo bar")

        roots = {self.primary_root_name: {}}
        for os_name in ["windows_path", "linux_path", "mac_path"]:
            # TODO make os specific roots
            roots[self.primary_root_name][os_name] = self.tank_temp

        if self._do_io:
            roots_path = os.path.join(self.pipeline_config_root, "config", "core", "roots.yml")
            roots_file = open(roots_path, "w")
            roots_file.write(yaml.dump(roots))
            roots_file.close()

        # clear bundle in-memory cache
        sgtk.descriptor.io_descriptor.factory.g_cached_instances = {}

        if self._do_io:
            self.pipeline_configuration = sgtk.pipelineconfig_factory.from_path(self.pipeline_config_root)
            self.tk = tank.Tank(self.pipeline_configuration)

        # set up mockgun and make sure shotgun connection calls route via mockgun
        self.mockgun = mockgun.Shotgun("http://unit_test_mock_sg", "mock_user", "mock_key")
        # fake a version response from the server
        self.mockgun.server_info = {"version": (7, 0, 0)}

        self._mock_return_value("tank.util.shotgun.connection.get_associated_sg_base_url", "http://unit_test_mock_sg")
        self._mock_return_value("tank.util.shotgun.connection.create_sg_connection", self.mockgun)
        self._mock_return_value("tank.util.shotgun.get_associated_sg_base_url", "http://unit_test_mock_sg")
        self._mock_return_value("tank.util.shotgun.create_sg_connection", self.mockgun)

        # add project to mock sg and path cache db
        if self._do_io:
            self.add_production_path(self.project_root, self.project)

        # add pipeline configuration
        self.add_to_sg_mock_db(self.project)
        self.add_to_sg_mock_db(self.sg_pc_entity)

        # add local storage
        self.primary_storage = {"type": "LocalStorage",
                                "id": 7777,
                                "code": self.primary_root_name,
                                "windows_path": self.tank_temp,
                                "linux_path": self.tank_temp,
                                "mac_path": self.tank_temp}

        self.add_to_sg_mock_db(self.primary_storage)

        # back up the authenticated user in case a unit test doesn't clean up correctly.
        self._authenticated_user = sgtk.get_authenticated_user()
示例#12
0
    def _return_repo_path(self, project_name):
        """
        Use Shotgun (Toolkit and Database) to get data
        and return the correct code repo root path for
        the Project that Toolkit launched.
        @return str repo_path: The root of the path
                               based on information
                               gleaned from Shotgun.
        """
        repo_path = None

        LOGGER.debug(MY_SEP)

        shotgun_inst = sgtk.api.shotgun.connection.get_sg_connection()
        sg_filters = [['project.Project.name', 'is', project_name]]
        sg_fields = [
            'id', 'code', 'project', 'sg_ss_tools_repo',
            'sg_ss_tools_repo_custom_path', 'windows_path'
        ]
        sgtk_configs = shotgun_inst.find('PipelineConfiguration', sg_filters,
                                         sg_fields)

        wanted_repo_key = None

        sg_auth = sgtk.get_authenticated_user()
        sgtk_core_user = sg_auth.login

        sgtk_module_path = sgtk.get_sgtk_module_path()
        if '\\' in sgtk_module_path:
            sgtk_module_path = sgtk_module_path.replace('\\', '/')
        sgtk_cfg_path = '/'.join(sgtk_module_path.split('/')[:5])
        LOGGER.debug('sgtk_module_path >> {}'.format(sgtk_module_path))
        LOGGER.debug('sgtk_cfg_path >> {}'.format(sgtk_cfg_path))

        for my_config in sgtk_configs:
            my_config_repo_key = my_config['sg_ss_tools_repo']
            my_config_repo_custom = my_config['sg_ss_tools_repo_custom_path']
            my_config_path = my_config['windows_path']
            if '\\' in my_config_path:
                my_config_path = my_config_path.replace('\\', '/')
                if my_config_path == sgtk_cfg_path:
                    wanted_repo_key = my_config_repo_key
                    m = 'wanted_repo_key >> {}'.format(wanted_repo_key)
                    LOGGER.debug(m)
                    break

        if wanted_repo_key:
            if wanted_repo_key == 'custom':
                # --- For developers to point to *any* pipeline code repository
                # --- as specified in the called Shotgun configuration...
                repo_path = my_config_repo_custom
                if '\\' in repo_path:
                    repo_path = repo_path.replace('\\', '/')

                if repo_path.endswith('/'):
                    repo_path = repo_path.strip('/')

                if not os.path.exists(repo_path):
                    m = 'Custom path does not exist! >> {}'.format(repo_path)
                    raise tank.TankError(m)
            elif wanted_repo_key == 'dev':
                # --- For developers to do individual tesing against clones of
                # --- same-named repositories within their X:/dev location...
                repo_path = 'X:/dev/ss_dev_{0}/{1}_repo'.format(
                    sgtk_core_user, project_name)
                # --- If it's not a Project-specific repo, we have to resort
                # --- to the generic studio repo...
                if not os.path.exists(repo_path):
                    repo_path = 'X:/dev/ss_dev_{0}/ss_studio_repo'.format(
                        sgtk_core_user, project_name)
            elif wanted_repo_key == 'project':
                # --- For everyone to launch using a Project-specific repo...
                repo_path = 'X:/tools/projects/{0}/{0}_repo'.format(
                    project_name)
            else:
                # --- For everyone to launch using the generic studio repo...
                repo_path = 'X:/tools/ss_studio_repo'
        LOGGER.debug(MY_SEP)

        # --- Check to make sure the resolved path, whatever it is, still
        # --- exists at the given location...
        # if not os.path.exists(repo_path):
        #     m = 'Resolved path does not exist! >> {}'.format(repo_path)
        #     raise tank.TankError(m)

        return repo_path
示例#13
0
    def setUp(self, parameters=None):
        """
        Sets up a Shotgun Mockgun instance with a project and a basic project scaffold on
        disk.
        
        :param parameters: Dictionary with additional parameters to control the setup.
                           The method currently supports the following parameters:
                           
                           - 'project_tank_name': 'name' - Set the tank_name of the project to 
                                                  something explicit. If not specified, this
                                                  will default to 'project_code' 
                           
                           - 'mockgun_schema_path': '/path/to/file' - Pass a specific schema to use with mockgun.
                                                    If not specified, the tk-core fixture schema 
                                                    will be used.

                           - 'mockgun_schema_entity_path': '/path/to/file' - Pass a specific entity schema to use with 
                                                           mockgun. If not specified, the tk-core fixture schema 
                                                           will be used. 
                                                               
        
        """
        
        parameters = parameters or {}
        
        if "project_tank_name" in parameters:
            project_tank_name = parameters["project_tank_name"]
        else:
            # default project name
            project_tank_name = "project_code"
        
        if "mockgun_schema_path" in parameters:
            mockgun_schema_path = parameters["mockgun_schema_path"]
        else:
            mockgun_schema_path = os.path.join(self.fixtures_root, "mockgun", "schema.pickle")
            
        if "mockgun_schema_entity_path" in parameters:
            mockgun_schema_entity_path = parameters["mockgun_schema_entity_path"]
        else:
            mockgun_schema_entity_path = os.path.join(self.fixtures_root, "mockgun", "schema_entity.pickle")
        
        # set up mockgun to use our schema
        mockgun.Shotgun.set_schema_paths(mockgun_schema_path, mockgun_schema_entity_path)
        
        self.tank_temp = TANK_TEMP
        self.init_cache_location = os.path.join(self.tank_temp, "init_cache.cache")

        self.cache_root = os.path.join(self.tank_temp, "cache_root")

        patch = mock.patch("tank.pipelineconfig_factory._get_cache_location", return_value=self.init_cache_location)
        patch.start()
        self.addCleanup(patch.stop)

        # Mock this so that authentication manager works even tough we are not in a config.
        # If we don't mock it than the path cache calling get_current_user will fail.
        patch = mock.patch(
            "tank.util.shotgun.get_associated_sg_config_data",
            return_value={"host": "https://somewhere.shotguntudio.com"}
        )
        patch.start()
        self.addCleanup(patch.stop)

        # define entity for test project
        self.project = {"type": "Project",
                        "id": 1,
                        "tank_name": project_tank_name,
                        "name": "project_name"}

        self.project_root = os.path.join(self.tank_temp, self.project["tank_name"].replace("/", os.path.sep) )
        
        self.pipeline_config_root = os.path.join(self.tank_temp, "pipeline_configuration")
          
        # move away previous data
        self._move_project_data()
        
        # create new structure
        os.makedirs(self.project_root)
        os.makedirs(self.pipeline_config_root)

        # project level config directories
        self.project_config = os.path.join(self.pipeline_config_root, "config")

        # create project cache directory
        project_cache_dir = os.path.join(self.pipeline_config_root, "cache")
        os.mkdir(project_cache_dir)
        
        # define entity for pipeline configuration
        self.sg_pc_entity = {"type": "PipelineConfiguration",
                             "code": "Primary", 
                             "id": 123, 
                             "project": self.project, 
                             "windows_path": self.pipeline_config_root,
                             "mac_path": self.pipeline_config_root,
                             "linux_path": self.pipeline_config_root}
        


        # add files needed by the pipeline config        
        pc_yml = os.path.join(self.pipeline_config_root, "config", "core", "pipeline_configuration.yml")
        pc_yml_data = ("{ project_name: %s, use_shotgun_path_cache: true, pc_id: %d, "
                       "project_id: %d, pc_name: %s}\n\n" % (self.project["tank_name"], 
                                                             self.sg_pc_entity["id"], 
                                                             self.project["id"], 
                                                             self.sg_pc_entity["code"]))
        self.create_file(pc_yml, pc_yml_data)
        
        loc_yml = os.path.join(self.pipeline_config_root, "config", "core", "install_location.yml")
        loc_yml_data = "Windows: '%s'\nDarwin: '%s'\nLinux: '%s'" % (self.pipeline_config_root, self.pipeline_config_root, self.pipeline_config_root)
        self.create_file(loc_yml, loc_yml_data)
        
        roots = {"primary": {}}
        for os_name in ["windows_path", "linux_path", "mac_path"]:
            #TODO make os specific roots
            roots["primary"][os_name] = self.tank_temp        
        roots_path = os.path.join(self.pipeline_config_root, "config", "core", "roots.yml")
        roots_file = open(roots_path, "w") 
        roots_file.write(yaml.dump(roots))
        roots_file.close()
                
        self.pipeline_configuration = sgtk.pipelineconfig_factory.from_path(self.pipeline_config_root)
        self.tk = tank.Tank(self.pipeline_configuration)
        
        # set up mockgun and make sure shotgun connection calls route via mockgun
        self.mockgun = mockgun.Shotgun("http://unit_test_mock_sg", "mock_user", "mock_key")
        # fake a version response from the server
        self.mockgun.server_info = {"version": (7, 0, 0)}

        patch = mock.patch("tank.util.shotgun.get_associated_sg_base_url", return_value="http://unit_test_mock_sg")
        patch.start()
        self.addCleanup(patch.stop)

        patch = mock.patch("tank.util.shotgun.create_sg_connection", return_value=self.mockgun)
        patch.start()
        self.addCleanup(patch.stop)

        # add project to mock sg and path cache db
        self.add_production_path(self.project_root, self.project)
        
        # add pipeline configuration
        self.add_to_sg_mock_db(self.sg_pc_entity)
        
        # add local storage
        self.primary_storage = {"type": "LocalStorage",
                                "id": 7777,
                                "code": "primary",
                                "windows_path": self.tank_temp,
                                "linux_path": self.tank_temp,
                                "mac_path": self.tank_temp }
        
        self.add_to_sg_mock_db(self.primary_storage)

        # back up the authenticated user in case a unit test doesn't clean up correctly.
        self._authenticated_user = sgtk.get_authenticated_user()
    def _return_repo_paths(self, project_name):
        """Use Shotgun (Toolkit and Database) to get data and return the
        correct code repo root paths for the Project that Toolkit launched.

        Args:
            project_name (str): The Project's full name in Shotgun.

        Returns:
            list:  The roots of the repo paths based on information gleaned
                from Shotgun.
        """
        repo_paths = []

        sg_auth = sgtk.get_authenticated_user()
        sgtk_core_user = sg_auth.login

        spr_path = self.return_spr_path()
        spr_split = os.path.basename(spr_path).split('_')
        v_maj = spr_split[2]
        v_min = spr_split[3]

        # --- Get the Project short name...
        proj_short_name = self.return_proj_short_name(project_name)

        # --- Get the SG configs...
        sgtk_configs = self.return_sgtk_configs(project_name)
        wanted_repo_key, my_config_repo_custom = self.return_wanted_repo_key(
            sgtk_configs)

        # --- First check ('custom')...
        if wanted_repo_key == 'custom':
            if my_config_repo_custom:
                if os.path.exists(my_config_repo_custom):
                    repo_path = my_config_repo_custom.replace('\\', '/')
                    repo_path = repo_path.strip('/')
                    if os.path.exists(repo_path):
                        repo_paths.append(repo_path)

        # --- Second check ('dev')...
        if wanted_repo_key == 'dev':
            # --- For developers to do individual tesing against clones of
            # --- same-named repositories within their X:/dev location...
            repo_path = 'X:/dev/ss_dev_{}'.format(sgtk_core_user)
            repo_path += '/{0}_pipeline_{1}_{2}_dev_master_repo'.format(
                proj_short_name, v_maj, v_min)
            # --- If it's not a Project-specific repo, we have to resort
            # --- to the generic studio repo dev clone...
            if not os.path.exists(repo_path):
                spr_base = os.path.basename(spr_path)

                repo_path = 'X:/dev/ss_dev_{0}/{1}'.format(
                    sgtk_core_user, spr_base)

            if os.path.exists(repo_path):
                repo_paths.append(repo_path)

        # --- Third check ('project')...
        if wanted_repo_key == 'project':
            repo_path = 'X:/tools/projects/{}'.format(project_name)
            repo_path += '/{0}_pipeline_{1}_{2}_repo'.format(
                proj_short_name, v_maj, v_min)

            if os.path.exists(repo_path):
                repo_paths.append(repo_path)

        # --- Always include the studio repo as the last repo path in the
        # --- list, and return the first entry from the list (the same if
        # --- there's only one entry in the list)...
        repo_paths.append(spr_path)

        return repo_paths
    def _run_external_process(self,
                              cache_path,
                              entity_type,
                              entity_id,
                              engine_name,
                              pre_cache=False):
        """
        Helper method. Executes the external caching process.

        :param int cache_path: Path to cache file to write
        :param str entity_type: Associated entity type
        :param int entity_id: Associated entity id
        :param str engine_name: Engine to start
        :param bool pre_cache: Whether to pre-cache all bundles during bootstrap

        :raises: SubprocessCalledProcessError
        """
        # launch external process to carry out caching.
        script = os.path.abspath(
            os.path.join(os.path.dirname(__file__), "..", "scripts",
                         "external_runner.py"))

        # We might have paths in sys.path that aren't in PYTHONPATH. We'll make
        # sure that we prepend our current pathing to that prior to spawning any
        # subprocesses.
        current_pypath = os.environ.get("PYTHONPATH")

        args_file = create_parameter_file(
            dict(
                action="cache_actions",
                cache_path=cache_path,
                configuration_uri=self.descriptor_uri,
                pipeline_config_id=self.pipeline_configuration_id,
                plugin_id=self.plugin_id,
                engine_name=engine_name,
                entity_type=entity_type,
                entity_id=entity_id,
                bundle_cache_fallback_paths=self._bundle.engine.sgtk.
                bundle_cache_fallback_paths,
                # the engine icon becomes the process icon
                icon_path=self._bundle.engine.icon_256,
                pre_cache=pre_cache,
                pythonpath=current_pypath,
            ))

        args = [
            self.interpreter, script,
            sgtk.bootstrap.ToolkitManager.get_core_python_path(), args_file
        ]
        logger.debug("Launching external script: %s", args)

        # Ensure the credentials are still valid before launching the command in
        # a separate process. We need do to this in advance because the process
        # that will be launched might not have PySide and as such won't be able
        # to prompt the user to re-authenticate.
        sgtk.get_authenticated_user().refresh_credentials()

        for path in sys.path:
            sgtk.util.prepend_path_to_env_var("PYTHONPATH", path)

        try:
            # Note: passing a copy of the environment in resolves some odd behavior with
            # the environment of processes spawned from the external_runner. This caused
            # some very bad behavior where it looked like PYTHONPATH was inherited from
            # this top-level environment rather than what is being set in external_runner
            # prior to launch. This is less critical here when caching configs, because
            # we're unlikely to spawn additional processes from the external_runner, but
            # just to cover our backsides, this is safest.
            output = subprocess_check_output(args, env=os.environ.copy())
            logger.debug("External caching complete. Output: %s" % output)
        finally:
            # Leave PYTHONPATH the way we found it.
            if current_pypath is None:
                del os.environ["PYTHONPATH"]
            else:
                os.environ["PYTHONPATH"] = current_pypath

            # clean up temp file
            sgtk.util.filesystem.safe_delete_file(args_file)
示例#16
0
    def _return_repo_path(self, project_name):
        """
        Use Shotgun (Toolkit and Database) to get data
        and return the correct code repo root path for
        the Project that Toolkit launched.
        @return str repo_path: The root of the path
                               based on information
                               gleaned from Shotgun.
        """
        repo_path = None

        logger.debug(my_sep)

        shotgun_inst = sgtk.api.shotgun.connection.get_sg_connection()
        sg_filters = [['project.Project.name', 'is', project_name]]
        sg_fields = [
            'id', 'code', 'project', 'sg_ss_tools_repo', 'windows_path'
        ]
        sgtk_configs = shotgun_inst.find('PipelineConfiguration', sg_filters,
                                         sg_fields)

        wanted_repo_key = None

        sg_auth = sgtk.get_authenticated_user()
        sgtk_core_user = sg_auth.login

        sgtk_module_path = sgtk.get_sgtk_module_path()
        if '\\' in sgtk_module_path:
            sgtk_module_path = sgtk_module_path.replace('\\', '/')
        sgtk_cfg_path = '/'.join(sgtk_module_path.split('/')[:5])
        logger.debug('sgtk_module_path >> {}'.format(sgtk_module_path))
        logger.debug('sgtk_cfg_path >> {}'.format(sgtk_cfg_path))

        for my_config in sgtk_configs:
            my_config_repo_key = my_config['sg_ss_tools_repo']
            my_config_path = my_config['windows_path']
            if '\\' in my_config_path:
                my_config_path = my_config_path.replace('\\', '/')
                if my_config_path == sgtk_cfg_path:
                    wanted_repo_key = my_config_repo_key
                    logger.debug(
                        'wanted_repo_key >> {}'.format(wanted_repo_key))
                    break

        if wanted_repo_key:
            if wanted_repo_key == 'dev':
                repo_path = 'X:/dev/ss_dev_{0}/{1}_repo'.format(
                    sgtk_core_user, project_name)
                # --- If it's not a Project-specific repo, we have to resort to
                # --- the generic studio repo...
                if not os.path.exists(repo_path):
                    repo_path = 'X:/dev/ss_dev_{0}/ss_studio_repo'.format(
                        sgtk_core_user, project_name)
            elif wanted_repo_key == 'project':
                repo_path = 'X:/tools/projects/{0}/{0}_repo'.format(
                    project_name)
            else:
                repo_path = 'X:/tools/ss_studio_repo'
        logger.debug(my_sep)

        return repo_path
示例#17
0
    def setUp(self, parameters=None):
        """
        Sets up a Shotgun Mockgun instance with a project and a basic project scaffold on
        disk.

        :param parameters: Dictionary with additional parameters to control the setup.
                           The method currently supports the following parameters:

                           - 'project_tank_name': 'name' - Set the tank_name of the project to
                                                  something explicit. If not specified, this
                                                  will default to 'project_code'

                           - 'mockgun_schema_path': '/path/to/file' - Pass a specific schema to use with mockgun.
                                                    If not specified, the tk-core fixture schema
                                                    will be used.

                           - 'mockgun_schema_entity_path': '/path/to/file' - Pass a specific entity schema to use with
                                                           mockgun. If not specified, the tk-core fixture schema
                                                           will be used.


        """
        # Override SHOTGUN_HOME so that unit tests can be sandboxed.
        self._old_shotgun_home = os.environ.get(self.SHOTGUN_HOME)
        os.environ[self.SHOTGUN_HOME] = TANK_TEMP

        # Make sure the global settings instance has been reset so anything from a previous test doesn't
        # leak into the next one.
        UserSettings.clear_singleton()

        parameters = parameters or {}

        if "project_tank_name" in parameters:
            project_tank_name = parameters["project_tank_name"]
        else:
            # default project name
            project_tank_name = "project_code"

        # now figure out mockgun location
        # 1. see if we have it explicitly specified in the parameters
        # 2. if not, check if the fixtures location has a mockgun folder
        # 3. if not, fall back on built in mockgun fixtures

        if "mockgun_schema_path" in parameters:
            mockgun_schema_path = parameters["mockgun_schema_path"]

        elif os.path.exists(os.path.join(self.fixtures_root, "mockgun")):
            mockgun_schema_path = os.path.join(
                self.fixtures_root,
                "mockgun",
                "schema.pickle"
            )

        else:
            # use the std core fixtures
            mockgun_schema_path = os.path.join(
                self.tank_source_path,
                "tests",
                "fixtures",
                "mockgun",
                "schema.pickle"
            )


        if "mockgun_schema_entity_path" in parameters:
            mockgun_schema_entity_path = parameters["mockgun_schema_entity_path"]

        elif os.path.exists(os.path.join(self.fixtures_root, "mockgun")):
            mockgun_schema_entity_path = os.path.join(
                self.fixtures_root,
                "mockgun",
                "schema_entity.pickle"
            )

        else:
            # use the std core fixtures
            mockgun_schema_entity_path = os.path.join(
                self.tank_source_path,
                "tests",
                "fixtures",
                "mockgun",
                "schema_entity.pickle"
            )

        # set up mockgun to use our schema
        mockgun.Shotgun.set_schema_paths(mockgun_schema_path, mockgun_schema_entity_path)

        self.tank_temp = TANK_TEMP

        self.cache_root = os.path.join(self.tank_temp, "cache_root")

        # Mock this so that authentication manager works even tough we are not in a config.
        # If we don't mock it than the path cache calling get_current_user will fail.
        self._mock_return_value(
            "tank.util.shotgun.get_associated_sg_config_data",
            {"host": "https://somewhere.shotguntudio.com"}
        )

        # define entity for test project
        self.project = {"type": "Project",
                        "id": 1,
                        "tank_name": project_tank_name,
                        "name": "project_name"}

        self.project_root = os.path.join(self.tank_temp, self.project["tank_name"].replace("/", os.path.sep) )

        self.pipeline_config_root = os.path.join(self.tank_temp, "pipeline_configuration")

        # move away previous data
        self._move_project_data()

        # create new structure
        os.makedirs(self.project_root)
        os.makedirs(self.pipeline_config_root)

        # project level config directories
        self.project_config = os.path.join(self.pipeline_config_root, "config")

        # create project cache directory
        project_cache_dir = os.path.join(self.pipeline_config_root, "cache")
        os.mkdir(project_cache_dir)

        # define entity for pipeline configuration
        self.sg_pc_entity = {"type": "PipelineConfiguration",
                             "code": "Primary",
                             "id": 123,
                             "project": self.project,
                             "windows_path": self.pipeline_config_root,
                             "mac_path": self.pipeline_config_root,
                             "linux_path": self.pipeline_config_root}



        # add files needed by the pipeline config
        pc_yml = os.path.join(self.pipeline_config_root, "config", "core", "pipeline_configuration.yml")
        pc_yml_data = ("{ project_name: %s, use_shotgun_path_cache: true, pc_id: %d, "
                       "project_id: %d, pc_name: %s}\n\n" % (self.project["tank_name"],
                                                             self.sg_pc_entity["id"],
                                                             self.project["id"],
                                                             self.sg_pc_entity["code"]))
        self.create_file(pc_yml, pc_yml_data)

        loc_yml = os.path.join(self.pipeline_config_root, "config", "core", "install_location.yml")
        loc_yml_data = "Windows: '%s'\nDarwin: '%s'\nLinux: '%s'" % (self.pipeline_config_root, self.pipeline_config_root, self.pipeline_config_root)
        self.create_file(loc_yml, loc_yml_data)

        # inject this file which toolkit is probing for to determine
        # if an installation has been localized.
        localize_token_file = os.path.join(self.pipeline_config_root, "install", "core", "_core_upgrader.py")
        self.create_file(localize_token_file, "foo bar")

        roots = {"primary": {}}
        for os_name in ["windows_path", "linux_path", "mac_path"]:
            #TODO make os specific roots
            roots["primary"][os_name] = self.tank_temp
        roots_path = os.path.join(self.pipeline_config_root, "config", "core", "roots.yml")
        roots_file = open(roots_path, "w")
        roots_file.write(yaml.dump(roots))
        roots_file.close()

        # clear bundle in-memory cache
        sgtk.descriptor.io_descriptor.factory.g_cached_instances = {}

        self.pipeline_configuration = sgtk.pipelineconfig_factory.from_path(self.pipeline_config_root)
        self.tk = tank.Tank(self.pipeline_configuration)

        # set up mockgun and make sure shotgun connection calls route via mockgun
        self.mockgun = mockgun.Shotgun("http://unit_test_mock_sg", "mock_user", "mock_key")
        # fake a version response from the server
        self.mockgun.server_info = {"version": (7, 0, 0)}

        self._mock_return_value("tank.util.shotgun.get_associated_sg_base_url", "http://unit_test_mock_sg")
        self._mock_return_value("tank.util.shotgun.create_sg_connection", self.mockgun)

        # add project to mock sg and path cache db
        self.add_production_path(self.project_root, self.project)

        # add pipeline configuration
        self.add_to_sg_mock_db(self.sg_pc_entity)

        # add local storage
        self.primary_storage = {"type": "LocalStorage",
                                "id": 7777,
                                "code": "primary",
                                "windows_path": self.tank_temp,
                                "linux_path": self.tank_temp,
                                "mac_path": self.tank_temp }

        self.add_to_sg_mock_db(self.primary_storage)

        # back up the authenticated user in case a unit test doesn't clean up correctly.
        self._authenticated_user = sgtk.get_authenticated_user()
#!python2
# -*- coding:utf-8 -*-
#coding=gbk

import sgtk
import os, sys, threading
import busyDialog
import time, pprint
import Queue
import ctypes, inspect
from sgtk.platform.pyqt import QtCore, QtGui, QtWidgets

logger = sgtk.platform.get_logger(__name__)

sg = sgtk.get_authenticated_user().create_sg_connection()


def show_dialog(app_instance):
    app_instance.engine.show_dialog("Batch Publisher...", app_instance,
                                    BatchPublisherUI)


def _async_raise(tid, exctype):
    tid = ctypes.c_long(tid)
    if not inspect.isclass(exctype):
        exctype = type(exctype)
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid,
                                                     ctypes.py_object(exctype))
    if res == 0:
        raise ValueError("invalid thread id")
    elif res != 1:
示例#19
0
    def _setUp(self, parameters):
        """
        See documentation for setUp.
        """
        self.addCleanup(self._assert_teardown_called)
        # Override SHOTGUN_HOME so that unit tests can be sandboxed.
        self._old_shotgun_home = os.environ.get(self.SHOTGUN_HOME)
        os.environ[self.SHOTGUN_HOME] = TANK_TEMP

        # Make sure the global settings instance has been reset so anything from a previous test doesn't
        # leak into the next one.
        UserSettings.clear_singleton()

        parameters = parameters or {}

        self._do_io = parameters.get("do_io", True)

        # now figure out mockgun location
        # 1. see if we have it explicitly specified in the parameters
        # 2. if not, check if the fixtures location has a mockgun folder
        # 3. if not, fall back on built in mockgun fixtures

        if "mockgun_schema_path" in parameters:
            mockgun_schema_path = parameters["mockgun_schema_path"]

        elif os.path.exists(os.path.join(self.fixtures_root, "mockgun")):
            mockgun_schema_path = os.path.join(self.fixtures_root, "mockgun",
                                               "schema.pickle")

        else:
            # use the std core fixtures
            mockgun_schema_path = os.path.join(self.tank_source_path, "tests",
                                               "fixtures", "mockgun",
                                               "schema.pickle")

        if "mockgun_schema_entity_path" in parameters:
            mockgun_schema_entity_path = parameters[
                "mockgun_schema_entity_path"]

        elif os.path.exists(os.path.join(self.fixtures_root, "mockgun")):
            mockgun_schema_entity_path = os.path.join(self.fixtures_root,
                                                      "mockgun",
                                                      "schema_entity.pickle")

        else:
            # use the std core fixtures
            mockgun_schema_entity_path = os.path.join(
                self.tank_source_path,
                "tests",
                "fixtures",
                "mockgun",
                "schema_entity.pickle",
            )

        # set up mockgun to use our schema
        mockgun.Shotgun.set_schema_paths(mockgun_schema_path,
                                         mockgun_schema_entity_path)

        # Mock this so that authentication manager works even tough we are not in a config.
        # If we don't mock it than the path cache calling get_current_user will fail.
        self._mock_return_value(
            "tank.util.shotgun.connection.get_associated_sg_config_data",
            {"host": "https://somewhere.shotgunstudio.com"},
        )

        # set up mockgun and make sure shotgun connection calls route via mockgun
        self.mockgun = mockgun.Shotgun("http://unit_test_mock_sg", "mock_user",
                                       "mock_key")
        # fake a version response from the server
        self.mockgun.server_info = {"version": (7, 0, 0)}

        self._mock_return_value(
            "tank.util.shotgun.connection.get_associated_sg_base_url",
            "http://unit_test_mock_sg",
        )
        self._mock_return_value(
            "tank.util.shotgun.connection.create_sg_connection", self.mockgun)
        self._mock_return_value("tank.util.shotgun.get_associated_sg_base_url",
                                "http://unit_test_mock_sg")
        self._mock_return_value("tank.util.shotgun.create_sg_connection",
                                self.mockgun)

        # now, set up a project, pipeline configuration and storage root for testing
        # The name to use for our primary storage
        self.primary_root_name = parameters.get("primary_root_name",
                                                "unit_tests")
        self.tank_temp = TANK_TEMP
        self.cache_root = os.path.join(self.tank_temp, "cache_root")

        # Initialize storage roots
        self.roots = {self.primary_root_name: {}}
        for os_name in ["windows_path", "linux_path", "mac_path"]:
            # TODO make os specific roots
            self.roots[self.primary_root_name][os_name] = self.tank_temp

        # initialize list of projects for testing.
        if "project_tank_name" in parameters:
            project_tank_name = parameters["project_tank_name"]
        else:
            # default project name
            project_tank_name = "project_code"

        self.project, self.project_root = self.create_project(
            {"tank_name": project_tank_name})
        (
            self.sg_pc_entity,
            self.pipeline_configuration,
            self.pipeline_config_root,
            self.project_config,
            self.tk,
        ) = self.create_pipeline_configuration(self.project,
                                               {"code": "Primary"})

        if self._do_io:
            # add the project root to the production path (once self.tk is initialized)
            self.add_production_path(self.project_root, self.project)

        # add local storage
        self.primary_storage = {
            "type": "LocalStorage",
            "id": 7777,
            "code": self.primary_root_name,
            "windows_path": self.tank_temp,
            "linux_path": self.tank_temp,
            "mac_path": self.tank_temp,
        }
        self.add_to_sg_mock_db(self.primary_storage)

        # back up the authenticated user in case a unit test doesn't clean up correctly.
        self._authenticated_user = sgtk.get_authenticated_user()
        sgtk.util.login.g_shotgun_current_user_cache = "unknown"
        sgtk.util.login.g_shotgun_user_cache = "unknown"