Beispiel #1
0
def createDir(path):
    """ Create a directory with the specified path.
	"""
    path = os.path.normpath(path)

    if os.path.isdir(path):
        verbose.print_("Directory already exists: %s" % path)
        pass

    else:
        try:
            os.makedirs(path)

            # Hide the folder if its name starts with a dot, as these files
            # are not automatically hidden on Windows
            if os.environ['IC_RUNNING_OS'] == "Windows":
                if os.path.basename(path).startswith('.'):
                    setHidden(path)

            verbose.print_(
                'mkdir "%s"' %
                path)  # This causes an error if user config dir doesn't exist
            return path

        except:
            verbose.error("Cannot create directory: %s" % path)
            return False
Beispiel #2
0
	def save(self):
		""" Save data.
		"""
		if self.j.save():
			verbose.message("Job database saved.")
			return True
		else:
			verbose.error("Job database could not be saved.")
			return False
Beispiel #3
0
	def saveAppPaths(self):
		""" Save the application paths to the data file.
		"""
		self.storeAppPathOSX()
		self.storeAppPathLinux()
		self.storeAppPathWin()

		if self.ap.save():
			verbose.message("Application paths data file saved.")
			return True
		else:
			verbose.error("Application paths data file could not be saved.")
			return False
Beispiel #4
0
	def openFile(self):
		""" Dialog accept function.
		"""
		try:
			for item in self.ui.fileBrowser_treeWidget.selectedItems():
				filename = item.text(4)

		except ValueError:
			verbose.error("Nothing selected.")
			return False

		if self.session.file_open(filename):
			self.returnValue = filename
			self.accept()
    def createShots(self):
        """ Create the shot(s).

		"""
        success = 0
        existing = 0
        failure = 0
        shots_created = ""
        shots_existing = ""
        shots_failed = ""
        dialog_msg = ""

        for shot in self.shots_to_create:
            shot_datafile = self.getShotDatafile(shot)
            os_wrapper.createDir(os.path.dirname(shot_datafile))

            if self.shot_data.load(shot_datafile):
                existing += 1
                shots_existing += shot + "\n"
            elif self.shot_data.save():
                success += 1
                shots_created += shot + "\n"
            else:
                failure += 1
                shots_failed += shot + "\n"

        if success:
            message = "%d %s created successfully: " % (
                success, verbose.pluralise('shot', success))
            dialog_msg += "%s\n%s\n" % (message, shots_created)
            verbose.message(message + shots_created)

        if existing:
            message = "The following %d shot(s) were not created as they already exist: " % existing
            dialog_msg += "%s\n%s\n" % (message, shots_existing)
            verbose.warning(message + shots_existing)

        if failure:
            message = "The following %d shot(s) could not be created - please check write permissions and try again: " % failure
            dialog_msg += "%s\n%s\n" % (message, shots_failed)
            verbose.error(message + shots_failed)

        # Confirmation dialog
        dialog_title = "Shot Creator Results"
        dialog = prompt.dialog()
        dialog.display(dialog_msg, dialog_title, conf=True)

        self.populateShots()
Beispiel #6
0
def change_version(input_version, value, absolute=False):
    """ Change the version number.
		If absolute is True, set the version to the given value.
		Otherwise, adjust the existing value by the given value.
	"""
    if absolute:
        new_version = value
    else:
        new_version = input_version + value

    # Ensure the new value is within the allowed range
    if __min_version__ <= new_version <= __max_version__:
        return new_version
    else:
        verbose.error("Version number out of bounds.")
        return input_version
Beispiel #7
0
def move(source, destination, quiet=False):
    """ Move a file or folder.
	"""
    src = os.path.normpath(source)
    dst = os.path.normpath(destination)

    if not quiet:
        verbose.print_('move "%s" -> "%s"' % (src, dst))
    try:
        shutil.move(src, dst)
        return True
    except:
        exc_type, exc_value, exc_traceback = sys.exc_info()
        msg = traceback.format_exception_only(exc_type, exc_value)[0]
        if not quiet:
            verbose.error(msg)
        return False
Beispiel #8
0
def remove(path, quiet=False):
    """ Removes files or folders recursively.
	"""
    path = os.path.normpath(path)

    try:
        if os.path.isfile(path):
            os.remove(path)
        elif os.path.isdir(path):
            shutil.rmtree(path)
        return True, path
    except:
        exc_type, exc_value, exc_traceback = sys.exc_info()
        msg = traceback.format_exception_only(exc_type, exc_value)[0]
        if not quiet:
            verbose.error(msg)
        return False, msg
Beispiel #9
0
	def addJob(self):
		""" Open the edit job dialog to add a new job.
		"""
		editJobDialog = edit_job.dialog(parent=self)
		if editJobDialog.display('', '$IC_JOBSROOT', os.environ['IC_VERSION'], True):
			if self.j.addJob(editJobDialog.jobName, editJobDialog.jobPath, editJobDialog.jobVersion, editJobDialog.jobActive):
				self.reloadJobs(reloadDatabase=False, selectItem=editJobDialog.jobName)
			else:
				errorMsg = "Could not create job as a job with the name '%s' already exists." % editJobDialog.jobName
				dialogMsg = errorMsg + "\nWould you like to create a job with a different name?"
				verbose.error(errorMsg)

				# Confirmation dialog
				dialogTitle = 'Job Not Created'
				dialog = prompt.dialog()
				if dialog.display(dialogMsg, dialogTitle):
					self.addJob()
Beispiel #10
0
def render_split(filename):
    #	if filename.startswith('.'):
    #		return
    #	if not pblChk.paddingChk(filename):
    #		return
    #	nameBody, padding, extension = filename.split('.')
    #	return nameBody, padding, extension

    # Parse filename
    try:
        base, ext = os.path.splitext(filename)
        prefix, framenumber = base.rsplit('.', 1)
        padding = len(framenumber)
        framenumber_int = int(framenumber)
        return prefix, framenumber, ext
    except ValueError:
        verbose.error("Could not parse sequence.")
        return  # False, False, False # need to return tuple to match successful return type
Beispiel #11
0
def autoDeploy():

    # Deploying commands organizer
    outputMsg = "Deploying GPS tools... "
    try:
        # Deploy commands organizer copying the file to user scenes directory
        # so it's not read directly from master file in pipeline.
        # There's a different commandsOrganizer.dat for osx/win due to file
        # path differences for icons.
        if os.environ['IC_RUNNING_OS'] == 'Windows':
            osdir = 'win'
        else:
            osdir = 'osx'
        src = os.path.join(os.environ['IC_BASEDIR'], 'rsc', 'realflow',
                           'realflow__env__', osdir, 'commandsOrganizer.dat')
        dst = os.path.join(os.environ['IC_REALFLOW_SCENES_DIR'], '.cmdsOrg',
                           'commandsOrganizer.dat')
        os_wrapper.copy(src, dst)
        verbose.message("%s Ok" % outputMsg)
    except:
        verbose.error("%s Failed" % outputMsg)
Beispiel #12
0
	def editJob(self):
		""" Open edit job dialog.
		"""
		item = self.ui.jobs_listWidget.selectedItems()[0]
		jobName = item.text()

		editJobDialog = edit_job.dialog(parent=self)
		if editJobDialog.display(jobName, self.j.getPath(jobName), self.j.getVersion(jobName), self.j.getEnabled(jobName)):
			self.j.enableJob(jobName, editJobDialog.jobActive)
			self.j.setVersion(jobName, editJobDialog.jobVersion)
			self.j.setPath(jobName, editJobDialog.jobPath)
			if self.j.renameJob(jobName, editJobDialog.jobName):  # Do this last as jobs are referenced by name
				self.reloadJobs(reloadDatabase=False, selectItem=editJobDialog.jobName)
			else:
				errorMsg = "Could not rename job as a job with the name '%s' already exists." % editJobDialog.jobName
				dialogMsg = errorMsg + "\nWould you still like to edit the job '%s'?" % jobName
				verbose.error(errorMsg)

				# Confirmation dialog
				dialogTitle = 'Job Not Created'
				dialog = prompt.dialog()
				if dialog.display(dialogMsg, dialogTitle):
					self.editJob()
Beispiel #13
0
    def loadPanel(self, category):
        """ Load the panel UI (and helper module if required).
			The exec function is called here to avoid the error: 'unqualified
			exec is not allowed in function because it contains a nested
			function with free variables' with Python 2.x.
		"""
        ui_file = "settings_%s_ui.ui" % category
        helper_module = 'settings_%s' % category
        panel_ui_loaded = False
        helper_module_loaded = False

        # Create new frame to hold properties UI & load into frame
        self.ui.settings_frame.close()
        try:
            uifile = os.path.join(os.environ['IC_FORMSDIR'], ui_file)
            self.ui.settings_frame = QtCompat.loadUi(uifile)
            self.ui.settings_verticalLayout.addWidget(self.ui.settings_frame)
            panel_ui_loaded = True
        except FileNotFoundError:
            message = "Could not open '%s' properties panel UI. " % category
            verbose.error(message)

        # Load helper module
        try:
            exec_str = 'from . import %s as sh; helper = sh.helper(self, self.ui.settings_frame)' % helper_module
            # print(exec_str)
            exec(exec_str)
            helper_module_loaded = True
        except ImportError:
            message = "Could not import '%s' module. " % helper_module
            verbose.warning(message)

        if panel_ui_loaded:  # and helper_module_loaded:
            return True
        else:
            return False
Beispiel #14
0
def submit_job(**kwargs):
    """ Submit job to Deadline.
	"""
    cmd_output = ""
    result_msg = ""

    # if kwargs is not None:
    # 	for key, value in kwargs.items():
    # 		print("%24s = %s" %(key, value))

    try:
        if kwargs['renderLayers']:  # Batch submission -----------------------
            # Generate submission info files
            num_jobs = 0
            job_info_file_list = []
            plugin_info_file_list = []
            for render_layer in re.split(
                    r',\s*',
                    kwargs['renderLayers']):  # may be better to pass as list
                kwargs['renderLayer'] = render_layer
                # kwargs['isMovie'] = False
                job_info_file = generate_job_info_file(**kwargs)
                job_info_file_list.append(job_info_file)
                plugin_info_file = generate_plugin_info_file(**kwargs)
                plugin_info_file_list.append(plugin_info_file)
                num_jobs += 1

            # Generate batch file
            batch_submission_file = generate_batch_file(
                kwargs['scene'], job_info_file_list, plugin_info_file_list)

            # Execute deadlinecommand
            cmd_result, cmd_output = os_wrapper.execute(
                [os.environ['RQ_DEADLINECOMMAND'], batch_submission_file])
            if cmd_result:
                result_msg = "Successfully submitted %d job(s) to Deadline." % num_jobs

        else:  # Single job submission ---------------------------------------
            # Generate submission info files
            kwargs['renderLayer'] = None
            job_info_file = generate_job_info_file(**kwargs)
            plugin_info_file = generate_plugin_info_file(**kwargs)

            # Execute deadlinecommand
            cmd_result, cmd_output = os_wrapper.execute([
                os.environ['RQ_DEADLINECOMMAND'], job_info_file,
                plugin_info_file
            ])
            if cmd_result:
                result_msg = "Successfully submitted job to Deadline."

        if cmd_result:
            result = True
            verbose.print_(cmd_output)  #.decode())
            verbose.message(result_msg)
        else:
            raise RuntimeError(cmd_output)

    except:  # Submission failed ---------------------------------------------
        result = False
        exc_type, exc_value, exc_traceback = sys.exc_info()
        traceback.print_exception(exc_type, exc_value, exc_traceback)
        result_msg = "Failed to submit job to Deadline."
        verbose.error(result_msg)
        if (exc_type == RuntimeError) and cmd_output:
            result_msg += "\n" + cmd_output
        else:
            result_msg += "\nCheck console output for details."
        #output_str = "Either the Deadline executable could not be found, or the submission info files could not be written."
        #output_str = traceback.format_exception_only(exc_type, exc_value)[0]

    return result, result_msg
Beispiel #15
0
    def setupUI(self,
                window_object,
                window_title="",
                ui_file="",
                stylesheet="",
                prefs_file=None,
                store_window_geometry=True):
        """ Setup the UI.
		"""
        verbose.debug("Window object: %s Parent: %s" % (self, self.parent))

        # Instantiate preferences data class
        if prefs_file is None:
            self.prefs = None
        else:
            self.prefs = self.createPrefs(prefs_file)

        # Define some global variables
        self.currentAttrStr = ""

        # Load UI & stylesheet
        found_ui_file = self.checkFilePath(ui_file,
                                           searchpath=[
                                               os.environ['IC_FORMSDIR'],
                                           ])
        if os.path.isfile(found_ui_file):
            self.ui = QtCompat.loadUi(found_ui_file, self)
        else:
            verbose.error("UI file does not exist: %s" % found_ui_file)

        # Store some system UI colours & define colour palette
        self.col = {}
        self.col['text'] = QtGui.QColor(204, 204, 204)
        self.col['disabled'] = QtGui.QColor(102, 102, 102)
        self.col['highlighted-text'] = QtGui.QColor(255, 255, 255)
        tmpWidget = QtWidgets.QWidget()
        self.col['sys-window'] = tmpWidget.palette().color(
            QtGui.QPalette.Window)
        self.col['sys-highlight'] = tmpWidget.palette().color(
            QtGui.QPalette.Highlight)
        # self.col['window'] = self.col['sys-window']
        self.col['highlight'] = self.col['sys-highlight']
        self.col['window'] = QtGui.QColor('#444444')
        # self.col['highlight'] = QtGui.QColor('#78909c')
        self.computeUIPalette()

        # Load and set stylesheet
        self.stylesheet = self.checkFilePath(stylesheet,
                                             searchpath=[
                                                 os.environ['IC_FORMSDIR'],
                                             ])
        self.loadStyleSheet()

        # Set window title
        self.setObjectName(window_object)
        if window_title:
            self.setWindowTitle(window_title)
        else:
            window_title = self.windowTitle()

        # Perform custom widget setup
        self.setupWidgets(self.ui)

        # Restore window geometry and state
        self.store_window_geometry = store_window_geometry
        if self.store_window_geometry:
            try:
                uiName = self.objectName()
                if os.environ['IC_ENV'] != 'STANDALONE':
                    uiName += "_" + os.environ['IC_ENV'].lower()
                self.settings = QtCore.QSettings(os.environ['IC_VENDOR'],
                                                 uiName)
                self.restoreGeometry(self.settings.value("geometry", ""))
                verbose.print_("Restoring window geometry for '%s'." %
                               self.objectName())
            except (KeyError, TypeError):
                verbose.warning("Could not restore window geometry for '%s'." %
                                self.objectName())

            # # Use QSettings to store window geometry and state.
            # # (Restore state may cause issues with PyQt5)
            # if os.environ['IC_ENV'] == 'STANDALONE':
            # 	verbose.print_("Restoring window geometry for '%s'." %self.objectName())
            # 	try:
            # 		self.settings = QtCore.QSettings(
            # 			os.environ['IC_VENDOR'], window_title)
            # 		self.restoreGeometry(self.settings.value("geometry", ""))
            # 		# self.restoreState(self.settings.value("windowState", ""))
            # 	except:
            # 		pass

            # # Makes Maya perform magic which makes the window stay on top in
            # # OS X and Linux. As an added bonus, it'll make Maya remember the
            # # window position.
            # elif os.environ['IC_ENV'] == 'MAYA':
            # 	self.setProperty("saveWindowPref", True)

            # elif os.environ['IC_ENV'] == 'NUKE':
            # 	pass

        # else:
        # 	# Move to centre of active screen
        # 	desktop = QtWidgets.QApplication.desktop()
        # 	screen = desktop.screenNumber(desktop.cursor().pos())
        # 	self.move(desktop.screenGeometry(screen).center() - self.frameGeometry().center())
        # 	# Move to centre of parent window
        # 	self.move(self.parent.frameGeometry().center() - self.frameGeometry().center())

        # Set up keyboard shortcuts
        self.shortcutUnloadStyleSheet = QtWidgets.QShortcut(self)
        self.shortcutUnloadStyleSheet.setKey('Ctrl+Shift+R')
        self.shortcutUnloadStyleSheet.activated.connect(self.unloadStyleSheet)

        self.shortcutReloadStyleSheet = QtWidgets.QShortcut(self)
        self.shortcutReloadStyleSheet.setKey('Ctrl+R')
        self.shortcutReloadStyleSheet.activated.connect(self.loadStyleSheet)
Beispiel #16
0
def parse(filepath,
          base_dir=os.environ['SCNMGR_SAVE_DIR'],
          convention=os.environ['SCNMGR_CONVENTION']):
    """ Parse the given filepath (relative to base_dir) based on a naming
		convention and return a dictionary of elements for processing.
		TODO: check shot, artist, discipline etc. against valid whitelist
	"""
    if not os.path.isfile(filepath):
        verbose.print_("Could not parse filename as file doesn't exist: %s" %
                       filepath)
        return None

    filepath = os.path.normpath(filepath)
    base_dir = os.path.normpath(base_dir)

    # Make filepath relative to base_dir
    if filepath.startswith(base_dir):
        filepath = filepath.replace(base_dir, '', 1)
        filepath = filepath.replace('\\', '/')  # Convert to forward slashes
        if filepath.startswith('/'):
            filepath = filepath.replace('/', '', 1)  # Remove leading slash

    # Find optional parts in naming convention
    # (only one optional section is allowed, if there are more, all optional
    # parts will be ignored.)
    valid_conventions = [convention.replace('[', '').replace(']', '')]
    pattern = r'\[.+?\]'
    optionals = re.findall(pattern, convention)
    if len(optionals) == 1:
        for i, optional in enumerate(optionals):
            valid_conventions.append(convention.replace(optional, '', i + 1))
    # print valid_conventions

    # # Find tokens in naming convention
    # pattern = r'<\w+>'
    # tokens = re.findall(pattern, convention)

    # # Remove duplicates & sort list
    # tokens = list(set(tokens))
    # # tokens.sort()
    # print tokens

    # # Generate regular expression to represent naming convention

    token_dict = {}
    success = False
    f = explode_path(filepath)
    for con in valid_conventions:
        c = explode_path(con)

        if same_structure(f, c):
            for i, dirs in enumerate(c):
                for j, token in enumerate(dirs):
                    value = f[i][j]
                    if token in token_dict:  # Sanity check duplicated tokens
                        if token_dict[token] != value:
                            verbose.error(
                                "Could not parse filename due to a token value mismatch."
                            )
                            return None
                    else:
                        token_dict[token] = value

            success = True

    if success:
        # print(token_dict)
        return token_dict

    else:
        msg = "The filename '%s' could not be parsed because it does not comply with the naming convention." % filepath
        for con in valid_conventions:
            msg += "\n" + con
        verbose.error(msg)
        return None