def setUp(self): """ Make sure the singleton is reset at the beginning of this test. """ super(UserSettingsTests, self).setUp() UserSettings.clear_singleton() self.addCleanup(UserSettings.clear_singleton)
def test_app_store_to_none(self, mock): """ Tests a file with a present but empty app store proxy setting. """ settings = UserSettings() self.assertTrue(settings.is_app_store_proxy_set()) self.assertEqual(settings.app_store_proxy, None)
def test_empty_file(self, mock): """ Tests a complete yaml file. """ settings = UserSettings() self.assertIsNone(settings.default_site) self.assertIsNone(settings.default_login) self.assertIsNone(settings.shotgun_proxy) self.assertFalse(settings.is_app_store_proxy_set())
def test_filled_file(self, mock): """ Tests a complete yaml file. """ settings = UserSettings() self.assertEqual(settings.default_site, "site") self.assertEqual(settings.default_login, "login") self.assertEqual(settings.shotgun_proxy, "http_proxy") self.assertTrue(settings.is_app_store_proxy_set()) self.assertEqual(settings.app_store_proxy, "app_store_http_proxy")
def test_bad_environment_variable(self): """ Test environment variables being set to files that don't exist. """ with patch.dict(os.environ, {"SGTK_PREFERENCES_LOCATION": "/a/b/c"}): with self.assertRaisesRegex(EnvironmentVariableFileLookupError, "/a/b/c"): UserSettings() with patch.dict(os.environ, {"SGTK_DESKTOP_CONFIG_LOCATION": "/d/e/f"}): with self.assertRaisesRegex(EnvironmentVariableFileLookupError, "/d/e/f"): UserSettings()
def test_boolean_setting(self): """ Tests that we can read a setting into a boolean. """ self.write_toolkit_ini_file(Custom={"valid": "ON", "invalid": "L"}) self.assertEqual(UserSettings().get_boolean_setting("Custom", "valid"), True) with self.assertRaisesRegex( TankError, "Invalid value 'L' in '.*' for setting 'invalid' in section 'Custom': expecting one of .*.", ): UserSettings().get_boolean_setting("Custom", "invalid")
def write_toolkit_ini_file(self, login_section={}, **kwargs): """ Creates an ini file in a unique location with the user settings. :param login_section: Dictionary of settings that will be stored in the [Login] section. :param **kwargs: Dictionary where the key is a section name and the value is a dictionary of the settings for that section. :returns: Path to the Toolkit ini file. """ # Create a unique folder for this test. folder = os.path.join(self.tank_temp, str(uuid.uuid4())) os.makedirs(folder) # Manually write the file as this is the format we're expecting the UserSettings # to parse. ini_file_location = os.path.join(folder, "toolkit.ini") with open(ini_file_location, "w") as f: f.writelines(["[Login]\n"]) for key, value in login_section.iteritems(): f.writelines(["%s=%s\n" % (key, value)]) for section in kwargs: f.writelines(["[%s]\n" % section]) for key, value in kwargs[section].iteritems(): f.writelines(["%s=%s\n" % (key, value)]) # The setUp phase cleared the singleton. So set the preferences environment variable and # instantiate the singleton, which will read the env var and open that location. with mock.patch.dict(os.environ, {"SGTK_PREFERENCES_LOCATION": ini_file_location}): UserSettings() return ini_file_location
def test_settings_enumeration(self): """ Tests that we can enumerate settings from a section. """ self.write_toolkit_ini_file({ "this": "is", "my": "boomstick" }, Custom={}) self.assertEqual( UserSettings().get_section_settings("missing section"), None) self.assertEqual(UserSettings().get_section_settings("Custom"), []) self.assertEqual(UserSettings().get_section_settings("Login"), ["this", "my"])
def test_custom_settings(self): """ Tests that we can read settings in any section of the file. """ self.write_toolkit_ini_file(Custom={"custom_key": "custom_value"}) self.assertEqual(UserSettings().get_setting("Custom", "custom_key"), "custom_value")
def test_system_proxy(self, mock): """ Tests the fallback on the operating system http proxy. """ http_proxy = "foo:[email protected]:80" # IP address of shotgunstudio.com with patch.dict(os.environ, {"http_proxy": "http://" + http_proxy}): settings = UserSettings() self.assertEqual(settings.shotgun_proxy, http_proxy)
def test_environment_variable_expansions(self, mock): """ Tests that setting an environment variable will be resolved. """ with patch.dict(os.environ, {"SGTK_TEST_SHOTGUN_SITE": "shotgun_site"}): settings = UserSettings() self.assertEqual(settings.default_site, "https://shotgun_site.shotgunstudio.com")
def test_integer_setting(self): """ Tests that we can read a setting into an integer """ self.write_toolkit_ini_file(Custom={ "valid": "1", "also_valid": "-1", "invalid": "L" }) self.assertEqual(UserSettings().get_integer_setting("Custom", "valid"), 1) self.assertEqual( UserSettings().get_integer_setting("Custom", "also_valid"), -1) with self.assertRaisesRegex( TankError, "Invalid value 'L' in '.*' for setting 'invalid' in section 'Custom': expecting integer.", ): UserSettings().get_integer_setting("Custom", "invalid")
def test_environment_variable_expansions(self): """ Tests that setting an environment variable will be resolved. """ self.write_toolkit_ini_file({ # Config parser represent empty settings as empty strings "default_site": "https://${SGTK_TEST_SHOTGUN_SITE}.shotgunstudio.com" }) with patch.dict(os.environ, {"SGTK_TEST_SHOTGUN_SITE": "shotgun_site"}): settings = UserSettings() self.assertEqual(settings.default_site, "https://shotgun_site.shotgunstudio.com")
def test_empty_settings(self): """ Tests a yaml file with the settings present but empty. """ self.write_toolkit_ini_file({ "default_site": "", "default_login": "", "http_proxy": "", "app_store_http_proxy": "" }) settings = UserSettings() self.assertEqual(settings.default_site, "") self.assertEqual(settings.default_login, "") self.assertEqual(settings.shotgun_proxy, "") self.assertEqual(settings.app_store_proxy, "")
def test_filled_file(self): """ Tests a complete yaml file. """ self.write_toolkit_ini_file({ "default_site": "site", "default_login": "******", "http_proxy": "http_proxy", "app_store_http_proxy": "app_store_http_proxy" }) settings = UserSettings() self.assertEqual(settings.default_site, "site") self.assertEqual(settings.default_login, "login") self.assertEqual(settings.shotgun_proxy, "http_proxy") self.assertEqual(settings.app_store_proxy, "app_store_http_proxy")
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"
def setUp(self): """ Sets up the next test's environment. """ TankTestBase.setUp(self) UserSettings.clear_singleton()
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()
def setUp(self): """ Sets up the next test's environment. """ ShotgunTestBase.setUp(self) UserSettings.clear_singleton()
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()