def __check_paths(self, houdini_version, expected_folders): """ Checks that the expected folders are gathered for the correct Houdini version. :param houdini_version: The version of Houdini as a tuple of three ints. :param expected_folders: The list of paths that we expect want to compare against the engine generated ones. :return: """ # Change what the engine thinks the Houdini version is. self.engine._houdini_version = houdini_version # Ask the engine for the otl paths. paths_from_engine = self.engine._get_otl_paths(self.app_otl_folder) # We would always expect to get the root otl folder returned. expected_folders.insert(0, self.app_otl_folder) # Handle forward and backwards slashes so that the comparison doesn't care. sanitized_paths_from_engine = [ ShotgunPath.from_current_os_path(path) for path in paths_from_engine ] sanitized_expected_paths = [ ShotgunPath.from_current_os_path(path) for path in expected_folders ] self.assertEqual( sanitized_paths_from_engine, sanitized_expected_paths, "Houdini version number was: v%s.%s.%s" % houdini_version, )
def test_otls_installed(self): """ Checks that the otls file get installed correctly in Houdini, and that Houdini reports them as installed. """ # The alembic app is added and it should have installed two otl files, # check that Houdini recognizes this. alembic_app = self.engine.apps["tk-houdini-alembicnode"] otl_path = self.engine._safe_path_join(alembic_app.disk_location, "otls") # The alembic node should have version folders, so remove root folder from the list, # and check that we have one path left which will be the version folder. otl_paths = self.engine._get_otl_paths(otl_path) otl_paths.remove(otl_path) self.assertTrue(len(otl_paths) == 1) # Now check both otls were installed in Houdini. sanitized_loaded_files = [ ShotgunPath.from_current_os_path(path) for path in hou.hda.loadedFiles() ] self.assertTrue( ShotgunPath.from_current_os_path( os.path.join(otl_paths[0], "sgtk_alembic.otl")) in sanitized_loaded_files) self.assertTrue( ShotgunPath.from_current_os_path( os.path.join(otl_paths[0], "sgtk_alembic_sop.otl")) in sanitized_loaded_files)
def test_transactions(self): """ Ensures the transaction flags are properly handled for a config. """ new_config_root = os.path.join(self.tank_temp, self.short_test_name) writer = ConfigurationWriter( ShotgunPath.from_current_os_path(new_config_root), self.mockgun) # Test standard transaction flow. # Non pending -> Pending -> Non pending self.assertEqual(False, writer.is_transaction_pending()) writer.start_transaction() self.assertEqual(True, writer.is_transaction_pending()) writer.end_transaction() self.assertEqual(False, writer.is_transaction_pending()) # Remove the transaction folder writer._delete_state_file(writer._TRANSACTION_START_FILE) writer._delete_state_file(writer._TRANSACTION_END_FILE) # Even if the marker is missing, the API should report no pending transactions since the # transaction folder doesn't even exist, which will happen for configurations written # with a previous version of core. self.assertEqual(False, writer.is_transaction_pending()) # We've deleted both the transaction files and now we're writing the end transaction file. # If we're in that state, we'll assume something is broken and say its pending since the # config was tinkered with. writer.end_transaction() self.assertEqual(True, writer.is_transaction_pending())
def setUp(self): # Makes sure every unit test run in its own sandbox. super(TestInterpreterFilesWriter, self).setUp() self._root = os.path.join(self.tank_temp, self.short_test_name) os.makedirs(self._root) self._cw = ConfigurationWriter( ShotgunPath.from_current_os_path(self._root), self.mockgun)
def test_load_snapshot(self): """ Tests loading a snapshot, there is no API method for this, so we are calling internal app functions. """ # Create a file for the test to load. file_path = self._create_file("banana") # Reset the scene so it won't prompt the test to save. self._reset_scene() handler = self.app.tk_multi_snapshot.Snapshot(self.app) handler._do_scene_operation("open", file_path) # Now check that the file Houdini has open is the same as the one we originally saved. self.assertEqual( ShotgunPath.from_current_os_path(file_path), ShotgunPath.from_current_os_path(hou.hipFile.name()), )
def _create_test_data(self, create_project): """ Creates test data, including - __pipeline_configuration, a shotgun entity dict. - optional __project entity dict, linked from the pipeline configuration - __descriptor, a sgtk.descriptor.Descriptor refering to a config on disk. - __cw, a ConfigurationWriter """ if create_project: self.__project = self.mockgun.create("Project", { "code": "TestWritePipelineConfigFile", "tank_name": "pc_tank_name" }) else: self.__project = None self.__pipeline_configuration = self.mockgun.create( "PipelineConfiguration", { "code": "PC_TestWritePipelineConfigFile", "project": self.__project }) self.__descriptor = sgtk.descriptor.create_descriptor( self.mockgun, sgtk.descriptor.Descriptor.CONFIG, dict(type="dev", path="/a/b/c")) config_root = os.path.join(self.tank_temp, self.id()) self.__cw = ConfigurationWriter( ShotgunPath.from_current_os_path(config_root), self.mockgun) os.makedirs(os.path.join(config_root, "config", "core"))
def test_transactions(self): """ Ensures the transaction flags are properly handled for a config. """ new_config_root = os.path.join(self.tank_temp, self.short_test_name) writer = ConfigurationWriter( ShotgunPath.from_current_os_path(new_config_root), self.mockgun ) # Test standard transaction flow. # Non pending -> Pending -> Non pending self.assertEqual(False, writer.is_transaction_pending()) writer.start_transaction() self.assertEqual(True, writer.is_transaction_pending()) writer.end_transaction() self.assertEqual(False, writer.is_transaction_pending()) # Remove the transaction folder writer._delete_state_file(writer._TRANSACTION_START_FILE) writer._delete_state_file(writer._TRANSACTION_END_FILE) # Even if the marker is missing, the API should report no pending transactions since the # transaction folder doesn't even exist, which will happen for configurations written # with a previous version of core. self.assertEqual(False, writer.is_transaction_pending()) # We've deleted both the transaction files and now we're writing the end transaction file. # If we're in that state, we'll assume something is broken and say its pending since the # config was tinkered with. writer.end_transaction() self.assertEqual(True, writer.is_transaction_pending())
def test_get_current_path(self): """ Tests the scene operation hooks current_path operation. """ # Create a temporary scene file, so we can test that we can get the current path to it. created_file = self._create_file("temp") # Make sure the scene file we created matches what Houdini believes to be the scene file. self.assertEqual(hou.hipFile.name(), created_file) result = self.scene_operation.get_current_path( self.app, self.scene_operation.NEW_FILE_ACTION, self.engine.context ) self.assertEqual( ShotgunPath.from_current_os_path(hou.hipFile.name()), ShotgunPath.from_current_os_path(result), )
def setUp(self): # Makes sure every unit test run in its own sandbox. super(TestInterpreterFilesWriter, self).setUp() self._root = os.path.join(self.tank_temp, self.short_test_name) os.makedirs(self._root) self._cw = ConfigurationWriter( ShotgunPath.from_current_os_path(self._root), self.mockgun )
def _create_test_data(self, create_project): """ Creates test data, including - __site_configuration, a shotgun entity dict. - optional __project entity dict, linked from the pipeline configuration - __descriptor, a sgtk.descriptor.Descriptor refering to a config on disk. - __cw, a ConfigurationWriter """ if create_project: self.__project = self.mockgun.create( "Project", { "code": "TestWritePipelineConfigFile", "tank_name": "pc_tank_name" } ) else: self.__project = None self.__site_configuration = self.mockgun.create( "PipelineConfiguration", { "code": "PC_TestWritePipelineConfigFile", "project": None } ) self.__project_configuration = self.mockgun.create( "PipelineConfiguration", { "code": "PC_TestWritePipelineConfigFile", "project": self.__project } ) self.__descriptor = sgtk.descriptor.create_descriptor( self.mockgun, sgtk.descriptor.Descriptor.CONFIG, dict(type="dev", path="/a/b/c") ) config_root = os.path.join(self.tank_temp, self.short_test_name) self.__cw = ConfigurationWriter( ShotgunPath.from_current_os_path(config_root), self.mockgun ) os.makedirs( os.path.join( config_root, "config", "core" ) )
def test_reset(self): """ Tests the scene operation hooks reset operation. """ # Create a temporary scene file, so we can test the reset works. created_file = self._create_file("temp") # Make sure the scene file we created matches what Houdini believes to be the scene file. self.assertEqual( ShotgunPath.from_current_os_path(hou.hipFile.name()), ShotgunPath.from_current_os_path(created_file), ) result = self.scene_operation.reset_current_scene( self.app, self.scene_operation.NEW_FILE_ACTION, self.engine.context ) self.assertTrue(result) # When we reset the file name should be untitled.hip self.assertEqual( ShotgunPath.from_current_os_path(hou.hipFile.name()), ShotgunPath.from_current_os_path("untitled.hip"), )
def test_save_file(self): """ Tests the scene operation hooks save operation. """ save_path = self._get_new_file_path("work_path", "cat") # test saving a new file. self.scene_operation.save_file( self.app, self.scene_operation.NEW_FILE_ACTION, self.engine.context, path=save_path, ) self.assertEqual( ShotgunPath.from_current_os_path(save_path), ShotgunPath.from_current_os_path(hou.hipFile.name()), ) # Now test saving over the same file. self.scene_operation.save_file( self.app, self.scene_operation.NEW_FILE_ACTION, self.engine.context )
def _create_configuration_writer(self): """ Creates a configuration writer that will write to a unique folder for this test. """ new_config_root = os.path.join(self.tank_temp, "new_configuration", self.short_test_name) shotgun_yml_root = os.path.join(new_config_root, "config", "core") # Ensures the location for the shotgun.yml exists. os.makedirs(shotgun_yml_root) writer = ConfigurationWriter( ShotgunPath.from_current_os_path(new_config_root), self.mockgun) writer.ensure_project_scaffold() return writer
def test_open_file(self): """ Tests the scene operation hooks open operation. """ created_file = self._create_file("dog") # Reset the scene so it is empty in preparation for opening the file we just saved. self._reset_scene() self.scene_operation.open_file( self.app, self.scene_operation.NEW_FILE_ACTION, self.engine.context, created_file, 1, False, ) self.assertEqual( ShotgunPath.from_current_os_path(created_file), ShotgunPath.from_current_os_path(hou.hipFile.name()), )
def test_execute(self): """ Ensure we can set up the project. """ self._wizard.set_project_disk_name(self.short_test_name) path = ShotgunPath.from_current_os_path( os.path.join(self.tank_temp, self.short_test_name, "pipeline") ) self._wizard.set_configuration_location(path.linux, path.windows, path.macosx) # Upload method not implemented on Mockgun yet, so skip that bit. with patch("tank_vendor.shotgun_api3.lib.mockgun.mockgun.Shotgun.upload"): with patch("tank.pipelineconfig_utils.get_core_api_version") as api_mock: api_mock.return_value = "HEAD" self._wizard.execute()
def _create_configuration_writer(self): """ Creates a configuration writer that will write to a unique folder for this test. """ new_config_root = os.path.join(self.tank_temp, "new_configuration", self.short_test_name) shotgun_yml_root = os.path.join(new_config_root, "config", "core") # Ensures the location for the shotgun.yml exists. os.makedirs(shotgun_yml_root) writer = ConfigurationWriter( ShotgunPath.from_current_os_path(new_config_root), self.mockgun ) writer.ensure_project_scaffold() return writer
def test_character_escaping(self): """ Ensure that the ' characte is properly escaped when writing out install_location.yml """ new_config_root = os.path.join(self.tank_temp, self.short_test_name, "O'Connell") writer = ConfigurationWriter( ShotgunPath.from_current_os_path(new_config_root), self.mockgun) install_location_path = os.path.join(new_config_root, "config", "core", "install_location.yml") os.makedirs(os.path.dirname(install_location_path)) writer.write_install_location_file() with open(install_location_path, "rt") as f: paths = yaml.safe_load(f) path = ShotgunPath(paths["Windows"], paths["Linux"], paths["Darwin"]) assert path.current_os == new_config_root
def test_get_core_settings(self): """ Ensure we can find the core settings. Given this is a unit test and not running off a real core, there's nothing more we can do at the moment. """ # Core is installed as # <studio-install>/install/core/python # This file is under the equivalent of # <studio-install>/install/core/tests/commands_tests/test_project_wizard.py # So we have to pop 4 folders to get back the equivalent location. install_location = os.path.normpath( os.path.join(os.path.dirname(__file__), "..", "..", "..", "..") ) self.assertEqual( self._wizard.get_core_settings(), { "core_path": ShotgunPath.from_current_os_path( install_location ).as_system_dict(), "localize": True, "pipeline_config": None, "using_runtime": True, }, )