### Get Badge Hook for tk-multi-workfiles2 Source: https://context7.com/shotgunsoftware/tk-multi-workfiles2/llms.txt Allows adding custom visual badges to work files and publishes in the file browser. It provides methods to generate badges for publishes and work files based on their details, and a helper to create QPixmap badges. ```python import sgtk from sgtk.platform.qt import QtGui HookClass = sgtk.get_hook_baseclass() class GetBadge(HookClass): """ Hook for generating badges for publishes and work files. """ def get_publish_badge(self, publish_details, publish_path, **kwargs): """ Generate a badge for a publish. :param publish_details: Dictionary with publish info (task, version, entity, etc.) :param publish_path: Path to the publish on disk :returns: QPixmap, QColor for badge, or None """ # Example: Add red badge for outdated publishes version = publish_details.get("version", 0) if version < 5: return QtGui.QColor(255, 100, 100) # Red badge return None def get_work_file_badge(self, work_file_details, work_file_path, **kwargs): """ Generate a badge for a work file. :param work_file_details: Dictionary with work file info :param work_file_path: Path to the work file on disk :returns: QPixmap, QColor for badge, or None """ # Example: Add green badge for editable files if work_file_details.get("editable", True): return QtGui.QColor(100, 255, 100) # Green badge return None def generate_badge_pixmap(self, badge_color): """ Generate a badge QPixmap from a QColor. :param badge_color: QColor for the badge :returns: QPixmap of the badge """ badge = QtGui.QPixmap(":/tk-multi-workfiles2/badge_default.png") painter = QtGui.QPainter() painter.begin(badge) try: painter.setCompositionMode(QtGui.QPainter.CompositionMode_SourceIn) painter.fillRect(badge.rect(), badge_color) finally: painter.end() return badge ``` -------------------------------- ### User Login Hook for tk-multi-workfiles2 Source: https://context7.com/shotgunsoftware/tk-multi-workfiles2/llms.txt Retrieves and stores user information for work files, supporting custom metadata tracking. It includes methods to get the file owner's login name and to log user save activity. ```python import os import sgtk HookClass = sgtk.get_hook_baseclass() class UserLogin(HookClass): """ Hook for retrieving and storing user login data for work files. """ def get_login(self, path, **kwargs): """ Get the login name of the user who owns/modified the file. :param path: Path to the work file :returns: Login name string or None """ if sgtk.util.is_windows(): try: return self._get_windows_file_owner(path) except: pass else: try: from pwd import getpwuid return getpwuid(os.stat(path).st_uid).pw_name except: pass return None def save_user(self, work_path, work_version, **kwargs): """ Save user login information when a work file is saved. :param work_path: Path where the work file was saved :param work_version: Version number of the saved work file """ # Example: Log user save activity app = self.parent user = app.context.user if user: app.log_debug( f"User {user.get('name')} saved {work_path} (v{work_version})" ) def _get_windows_file_owner(self, path): """Get file owner on Windows using Win32 API.""" import ctypes from ctypes import wintypes # Implementation uses Windows security APIs # to retrieve file ownership information advapi32 = ctypes.windll.advapi32 # ... Windows API calls to get file owner return None # Simplified for example ``` -------------------------------- ### Filter Publishes Hook in Python Source: https://context7.com/shotgunsoftware/tk-multi-workfiles2/llms.txt Allows customization of the publishes list returned from Flow Production Tracking. It filters the list, for example, to only show approved publishes. The hook takes a list of publish dictionaries and returns a filtered list. ```python import sgtk HookClass = sgtk.get_hook_baseclass() class FilterPublishes(HookClass): """ Hook to filter the list of publishes returned from Flow Production Tracking. """ def execute(self, publishes, **kwargs): """ Filter or modify the publishes list. :param publishes: List of dictionaries with 'sg_publish' key containing the Shotgun entity dictionary for a Published File :returns: Filtered list of publish dictionaries """ app = self.parent # Example: Filter to only show approved publishes filtered = [] for publish_dict in publishes: sg_publish = publish_dict.get("sg_publish", {}) status = sg_publish.get("sg_status_list") # Include all publishes or only approved ones if status is None or status == "apr": filtered.append(publish_dict) return filtered ``` -------------------------------- ### Initialize tk-multi-workfiles2 Application (Python) Source: https://context7.com/shotgunsoftware/tk-multi-workfiles2/llms.txt Initializes the Workfiles application by importing necessary modules and registering commands for File Open, File Save, and Context Change dialogs based on configuration settings. It checks for UI availability before proceeding. ```python import sgtk class MultiWorkFiles(sgtk.platform.Application): def init_app(self): """ Called as the application is being initialized. Registers commands based on app settings. """ self._tk_multi_workfiles = self.import_module("tk_multi_workfiles") if not self.engine.has_ui: self.logger.debug("No UI available. Workfiles2 will not initialize.") return # Register Change Context command if self.get_setting("show_change_context"): self.engine.register_command( "Change Context...", self.show_context_change_dlg, {"short_name": "change_context"} ) # Register File Open command if self.get_setting("show_file_open"): self.engine.register_command( "File Open...", self.show_file_open_dlg, {"short_name": "file_open"} ) # Register File Save command if self.get_setting("show_file_save"): self.engine.register_command( "File Save...", self.show_file_save_dlg, {"short_name": "file_save"} ) def show_file_open_dlg(self, use_modal_dialog=False): """Launch the main File Open UI""" self._tk_multi_workfiles.WorkFiles.show_file_open_dlg(use_modal_dialog) def show_file_save_dlg(self, use_modal_dialog=False): """Launch the main File Save UI""" self._tk_multi_workfiles.WorkFiles.show_file_save_dlg(use_modal_dialog) def show_context_change_dlg(self, use_modal_dialog=False): """Launch the Context Change UI""" self._tk_multi_workfiles.WorkFiles.show_context_change_dlg(use_modal_dialog) @property def context_change_allowed(self): """Specifies that context changes are supported by the app.""" return True ``` -------------------------------- ### Implement Deferred Queries for Entity Tree Building Source: https://github.com/shotgunsoftware/tk-multi-workfiles2/wiki/Documentation This configuration illustrates how to implement deferred queries for building the entity tree. It breaks down the data retrieval into two steps: an initial query for the top of the tree and a subsequent query for children as the user expands nodes. This approach enhances performance by loading data on demand. The `sub_hierarchy` setting defines the structure for retrieving child entities. ```yaml entities: - caption: Assets entity_type: Asset hierarchy: [sg_asset_type, code] filters: sub_hierarchy: entity_type: Task filters: link_field: entity hierarchy: [step] - caption: Shots entity_type: Shot filters: hierarchy: [sg_sequence, code] sub_hierarchy: entity_type: Task filters: link_field: entity hierarchy: [step] ``` -------------------------------- ### Configure Step Filtering for Task Retrieval Source: https://github.com/shotgunsoftware/tk-multi-workfiles2/wiki/Documentation This configuration snippet demonstrates how to set up step filtering for retrieving Tasks. It allows you to specify which Pipeline Steps should be considered when displaying Tasks in a tab, reducing the amount of data fetched from Shotgun. The `step_filter_on` setting controls the displayed steps, and `filters` further refines the selection. ```yaml - caption: Assets Tasks entity_type: Task step_filter_on: Asset filters: - [entity, type_is, Asset] hierarchy: [entity.Asset.sg_asset_type, entity, step, content] - caption: Shots Tasks entity_type: Task step_filter_on: Shot filters: - [entity, type_is, Shot] hierarchy: [entity.Shot.sg_sequence, entity, step, content] ``` -------------------------------- ### Configure File Extension Choices with YAML Templates Source: https://context7.com/shotgunsoftware/tk-multi-workfiles2/llms.txt Configure file extension choices in the save dialog using template tokens with alias definitions. This YAML configuration defines available extensions for Maya and Nuke, and how they are used in file path templates. ```yaml # templates.yml configuration for file extension dropdown keys: maya_extension: type: str choices: ma: Maya Ascii (.ma) mb: Maya Binary (.mb) default: ma alias: extension nuke_extension: type: str choices: nk: Nuke Script (.nk) nknc: Nuke Non-Commercial (.nknc) default: nk alias: extension paths: # Maya work file with extension choice maya_shot_work: definition: '@shot_root/work/maya/{name}.v{version}.{maya_extension}' root_name: 'primary' # Nuke work file with extension choice nuke_shot_work: definition: '@shot_root/work/nuke/{name}.v{version}.{nuke_extension}' root_name: 'primary' ``` -------------------------------- ### Configure Maya File Extension Choices in templates.yml Source: https://github.com/shotgunsoftware/tk-multi-workfiles2/wiki/Documentation This snippet shows how to configure the file extension dropdown in the File Save dialog by defining a token in the `templates.yml` file. It specifies the token name, available choices with UI-friendly descriptions, a default value, and an alias for the workfiles application. ```yaml maya_extension: type: str choices: ma: Maya Ascii (.ma) mb: Maya Binary (.mb) default: ma alias: extension ``` -------------------------------- ### Enable Step Filtering for Tasks in Shotgun Source: https://github.com/shotgunsoftware/tk-multi-workfiles2/wiki/Release-Notes This configuration enables step filtering for Tasks retrieved from Shotgun, allowing users to display only pipeline Steps linked to a particular Entity type. This improves performance by reducing the amount of data fetched. It is applicable when not using deferred queries and requires specifying the entity type for filtering. ```yaml - caption: Assets Tasks entity_type: Task step_filter_on: Asset filters: - [entity, type_is, Asset] hierarchy: [entity.Asset.sg_asset_type, entity, step, content] ``` -------------------------------- ### tk-multi-workfiles2 Configuration Settings (YAML) Source: https://context7.com/shotgunsoftware/tk-multi-workfiles2/llms.txt Defines configuration settings for tk-multi-workfiles2 using YAML. This includes dialog visibility, file template configurations, entity browsing tab settings, and options for file browser and save dialogs. ```yaml # Environment configuration for tk-multi-workfiles2 settings.tk-multi-workfiles2: # Dialog visibility show_file_open: true show_file_save: true show_change_context: false launch_at_startup: false # Template configuration for file locations template_work: maya_shot_work template_work_area: shot_work_area_maya template_publish: maya_shot_publish template_publish_area: shot_publish_area_maya # Entity tabs configuration entities: - caption: Assets entity_type: Task step_filter_on: Asset filters: - [entity, type_is, Asset] hierarchy: [entity.Asset.sg_asset_type, entity, step, content] - caption: Shots entity_type: Task step_filter_on: Shot filters: - [entity, type_is, Shot] hierarchy: [entity.Shot.sg_sequence, entity, step, content] # My Tasks configuration show_my_tasks: true my_tasks_filters: - [task_assignees, is, '{context.user}'] my_tasks_extra_display_fields: [] # File browser options file_browser_tabs: ['All', 'Working', 'Publishes'] file_extensions: [] auto_expand_tree: false allow_task_creation: true # Save options saveas_default_name: scene saveas_prefer_version_up: false # Sort fields for task list sort_fields: tasks: - { field_code: content, display_name: Task Name } - { field_code: due_date, display_name: Due Date } - { field_code: sg_status_list, display_name: Status } ``` -------------------------------- ### Customize File Browser UI with Python Hook Source: https://context7.com/shotgunsoftware/tk-multi-workfiles2/llms.txt The UI config hook customizes the appearance and display of items in the file browser, including thumbnails, titles, and details. It uses Python and the PyQt framework to define how different file item properties are rendered. ```python from datetime import datetime, timedelta import sgtk from sgtk.platform.qt import QtCore, QtGui HookClass = sgtk.get_hook_baseclass() class UIConfig(HookClass): """Hook to customize the main file view display.""" PUBLISHED_FILE_DETAILS = [ {"attr": "version", "default": "No version set", "format": "v%03d"}, {"attr": "published_by", "field": "name", "default": "Unknown"}, {"attr": "published_at", "default": "Unknown"}, ] WORK_FILE_DETAILS = [ {"attr": "version", "default": "No version set", "format": "v%03d"}, {"attr": "modified_by", "default": "Unknown"}, {"attr": "modified_at", "default": "Unknown"}, ] def get_item_thumbnail(self, item): """Returns the thumbnail for a model item.""" return item.data(QtCore.Qt.DecorationRole) def get_item_title(self, item): """Returns the title text for a model item.""" file_item = item.data(item.model().FILE_ITEM_ROLE) if file_item: return "{}".format(file_item.name) return "{}".format(item.data(QtCore.Qt.DisplayRole)) def get_item_details(self, item): """Returns detail strings for a model item.""" details = [] file_item = item.data(item.model().FILE_ITEM_ROLE) if file_item: detail_items = ( self.PUBLISHED_FILE_DETAILS if file_item.is_published else self.WORK_FILE_DETAILS ) for detail_item in detail_items: if hasattr(file_item, detail_item["attr"]): value = getattr(file_item, detail_item["attr"]) if value: if detail_item.get("format"): value = detail_item["format"] % value details.append(str(value)) return details def get_item_icons(self, item): """Returns icon overlays for a model item.""" result = {} file_item = item.data(item.model().FILE_ITEM_ROLE) if file_item: if not file_item.editable: result["float-top-right"] = QtGui.QPixmap( ":/tk-multi-workfiles2/padlock.png" ) if file_item.is_published: result["float-bottom-right"] = QtGui.QPixmap( ":/tk-multi-workfiles2/publish_icon.png" ) if file_item.badge: result["float-bottom-left"] = file_item.badge return result ``` -------------------------------- ### Configure Deferred Queries for Performance in YAML Source: https://context7.com/shotgunsoftware/tk-multi-workfiles2/llms.txt Deferred queries improve performance for large projects by loading data on-demand as the user expands tree nodes. This configuration is defined in YAML and specifies how entities and their sub-hierarchies should be loaded. ```yaml # Environment configuration with deferred queries for better performance settings.tk-multi-workfiles2: entities: # Assets with deferred Task loading - caption: Assets entity_type: Asset hierarchy: [sg_asset_type, code] filters: [] sub_hierarchy: entity_type: Task filters: [] link_field: entity hierarchy: [step] # Shots with deferred Task loading - caption: Shots entity_type: Shot hierarchy: [sg_sequence, code] filters: [] sub_hierarchy: entity_type: Task filters: [] link_field: entity hierarchy: [step] # Enable step filtering for improved query performance show_my_tasks: true auto_expand_tree: false ``` -------------------------------- ### Nuke Scene Operation Hook Source: https://context7.com/shotgunsoftware/tk-multi-workfiles2/llms.txt Handles file operations for Nuke, Hiero, and Nuke Studio. It differentiates logic based on whether the engine is running in Hiero or Nuke Studio mode. Supports operations like opening, saving, saving as, and resetting scripts, with prompts for unsaved changes. ```python import os import nuke import sgtk from sgtk import TankError from sgtk.platform.qt import QtGui HookClass = sgtk.get_hook_baseclass() class SceneOperation(HookClass): """Hook for Nuke/Hiero/Nuke Studio scene operations.""" def execute(self, operation, file_path, context, parent_action, file_version, read_only, **kwargs): """ Main hook entry point for Nuke operations. """ engine = self.parent.engine # Check for Hiero or Nuke Studio mode if hasattr(engine, "hiero_enabled") and (engine.hiero_enabled or engine.studio_enabled): return self._scene_operation_hiero_nukestudio( operation, file_path, context, parent_action, file_version, read_only, **kwargs ) # Standard Nuke operations if file_path: file_path = file_path.replace(os.path.sep, "/") if operation == "current_path": return nuke.root().name().replace(os.path.sep, "/") elif operation == "open": nuke.scriptOpen(file_path) elif operation == "save": nuke.scriptSave() elif operation == "save_as": old_path = nuke.root()["name"].value() try: nuke.root()["name"].setValue(file_path) nuke.scriptSaveAs(file_path, -1) except Exception as e: nuke.root()["name"].setValue(old_path) raise TankError("Failed to save scene %s", e) elif operation == "reset": while nuke.root().modified(): res = QtGui.QMessageBox.question( None, "Save your script?", "Your script has unsaved changes. Save before proceeding?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No | QtGui.QMessageBox.Cancel, ) if res == QtGui.QMessageBox.Cancel: return False elif res == QtGui.QMessageBox.No: break else: nuke.scriptSave() nuke.scriptClear() return True ``` -------------------------------- ### Use Maya File Extension Token in Maya Template Source: https://github.com/shotgunsoftware/tk-multi-workfiles2/wiki/Documentation This snippet demonstrates how to integrate the previously defined `maya_extension` token into a Maya-specific template in `templates.yml`. This allows the workfiles application to use the configured file extensions for saving Maya files. ```yaml maya_shot_work: definition: '@shot_root/work/maya/{name}.v{version}.{maya_extension}' root_name: 'primary' ``` -------------------------------- ### Custom Actions Hook for File Browser Source: https://context7.com/shotgunsoftware/tk-multi-workfiles2/llms.txt Enables the definition of custom right-click menu actions within the file browser for work files and published assets. It provides methods to generate available actions and execute them, allowing for custom workflows like opening files in external viewers or copying paths. ```python import sgtk HookBaseClass = sgtk.get_hook_baseclass() class CustomActions(HookBaseClass): """ Implementation of custom actions for work files and publishes. """ def generate_actions(self, file, work_versions, publish_versions, context, **kwargs): """ Generate a list of custom actions for the right-click context menu. :param file: Dictionary containing file info: - name: Toolkit name for the file - path: File path - version: File version number - type: 'work' or 'publish' For work files: modified_at, modified_by, read_only For publishes: published_at, published_by :param work_versions: List of all work file versions :param publish_versions: List of all publish versions :param context: The context/work area :returns: List of action dictionaries with 'name' and 'caption' keys """ actions = [] # Example: Add action to open in external viewer if file["type"] == "publish": actions.append({ "name": "open_in_rv", "caption": "Open in RV" }) # Example: Add action to copy path actions.append({ "name": "copy_path", "caption": "Copy Path to Clipboard" }) return actions def execute_action(self, action, file, work_versions, publish_versions, context, **kwargs): """ Execute the specified custom action. :param action: Name of action to execute :param file: File information dictionary :param work_versions: List of all work file versions :param publish_versions: List of all publish versions :param context: The context/work area :returns: True to close the dialog, False to keep it open """ if action == "copy_path": from sgtk.platform.qt import QtGui clipboard = QtGui.QApplication.clipboard() clipboard.setText(file["path"]) return False elif action == "open_in_rv": import subprocess subprocess.Popen(["rv", file["path"]]) return False return False ``` -------------------------------- ### Maya Scene Operations Hook Source: https://context7.com/shotgunsoftware/tk-multi-workfiles2/llms.txt Handles DCC-specific file operations for Maya scenes, including opening, saving, and resetting. It uses Maya commands and Shotgun Toolkit context to perform these actions. The hook supports operations like 'current_path', 'open', 'save', 'save_as', and 'reset'. ```Python import maya.cmds as cmds import sgtk from sgtk.platform.qt import QtGui HookClass = sgtk.get_hook_baseclass() class SceneOperation(HookClass): """ Hook called to perform an operation with the current scene. """ def execute(self, operation, file_path, context, parent_action, file_version, read_only, **kwargs): """ Main hook entry point for scene operations. :param operation: Scene operation to perform (current_path, open, save, save_as, reset) :param file_path: File path for open/save operations :param context: The context the file operation is being performed in :param parent_action: The parent action (open_file, new_file, save_file_as, version_up) :param file_version: Version/revision of file to open (None for latest) :param read_only: Whether file should be opened read-only :returns: Depends on operation type """ if operation == "current_path": # Return the current scene file path return cmds.file(query=True, sceneName=True) elif operation == "open": # Reset scene first, then open file cmds.file(new=True, force=True) cmds.file(file_path, open=True, force=True) elif operation == "save": # Save the current scene cmds.file(save=True) elif operation == "save_as": # Rename and save with correct file type cmds.file(rename=file_path) maya_file_type = None if file_path.lower().endswith(".ma"): maya_file_type = "mayaAscii" elif file_path.lower().endswith(".mb"): maya_file_type = "mayaBinary" if maya_file_type: cmds.file(save=True, force=True, type=maya_file_type) else: cmds.file(save=True, force=True) elif operation == "reset": # Reset scene to empty state with save prompt while cmds.file(query=True, modified=True): res = QtGui.QMessageBox.question( None, "Save your scene?", "Your scene has unsaved changes. Save before proceeding?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No | QtGui.QMessageBox.Cancel, ) if res == QtGui.QMessageBox.Cancel: return False elif res == QtGui.QMessageBox.No: break else: scene_name = cmds.file(query=True, sn=True) if not scene_name: cmds.SaveSceneAs() else: cmds.file(save=True) cmds.file(newFile=True, force=True) return True ``` -------------------------------- ### Copy File Hook for tk-multi-workfiles2 Source: https://context7.com/shotgunsoftware/tk-multi-workfiles2/llms.txt Handles copying files between locations, typically used when opening files from other user sandboxes. It ensures the target directory exists before copying the file. ```python import os import shutil import sgtk HookClass = sgtk.get_hook_baseclass() class CopyFile(HookClass): """ Hook called when a file needs to be copied. """ def execute(self, source_path, target_path, **kwargs): """ Copy a file from source to target location. :param source_path: Source file path to copy from :param target_path: Target file path to copy to """ # Create the target directory if it doesn't exist dirname = os.path.dirname(target_path) if not os.path.isdir(dirname): old_umask = os.umask(0) os.makedirs(dirname, 0o777) os.umask(old_umask) # Copy the file shutil.copy(source_path, target_path) ``` -------------------------------- ### Configure Deferred Queries for Hierarchical Data in Shotgun Source: https://github.com/shotgunsoftware/tk-multi-workfiles2/wiki/Release-Notes This configuration allows for deferred retrieval of hierarchical data from Shotgun, improving performance by fetching data only when needed. It supports defining entity types, filters, link fields, and hierarchy structures for nested data retrieval. This is particularly useful for applications displaying complex relationships like Shots and Tasks. ```yaml - caption: Shots entity_type: Shot filters: hierarchy: [sg_sequence, code] sub_hierarchy: entity_type: Task filters: link_field: entity hierarchy: [step] ``` -------------------------------- ### Create New Task Hook in Python Source: https://context7.com/shotgunsoftware/tk-multi-workfiles2/llms.txt Handles creating new tasks from within the Workfiles dialog with optional name validation. It provides methods to create a task name validator and to create a new task with specified details. The hook can raise a TankError on validation or creation failure. ```python import sgtk from sgtk.platform.qt import QtGui HookClass = sgtk.get_hook_baseclass() class CreateNewTaskHook(HookClass): """ Hook called to create a task for a given entity and step. """ def create_task_name_validator(self): """ Create a QValidator for task name field validation. :returns: A QtGui.QValidator derived object or None """ class NoSpacesValidator(QtGui.QValidator): def validate(self, text, pos): if " " in text: return QtGui.QValidator.Intermediate, text.replace(" ", "_"), pos return QtGui.QValidator.Acceptable, text, pos return NoSpacesValidator() def create_new_task(self, name, pipeline_step, entity, assigned_to=None): """ Create a new task with the specified information. :param name: Name of the task to be created :param pipeline_step: Dictionary with 'type' and 'id' keys for the Step :param entity: Dictionary with 'type' and 'id' keys for the Entity :param assigned_to: Optional user dictionary to assign the task to :returns: The created task dictionary :raises sgtk.TankError: On validation or creation error """ app = self.parent # Construct task data data = { "step": pipeline_step, "project": app.context.project, "entity": entity, "content": name, } if assigned_to: data["task_assignees"] = [assigned_to] # Create the task in Shotgun sg_result = app.shotgun.create("Task", data) if not sg_result: raise sgtk.TankError("Failed to create new task - reason unknown!") # Set status to In Progress try: app.shotgun.update("Task", sg_result["id"], {"sg_status_list": "ip"}) except: pass # Not all studios use IP status return sg_result ``` -------------------------------- ### Configure My Tasks Tab Filters in Workfiles2 Source: https://github.com/shotgunsoftware/tk-multi-workfiles2/wiki/Release-Notes This snippet shows how to configure custom filters for the 'My Tasks' tab in tk-multi-workfiles2. It allows users to specify conditions for filtering tasks, such as assignee and status. This configuration is done via a YAML-like structure. ```yaml my_tasks_filters: - [task_assignees, is, '{context.user}'] - [sg_status_list, not_in, [fin,omt]] ``` -------------------------------- ### Filter Work Files Hook in Python Source: https://context7.com/shotgunsoftware/tk-multi-workfiles2/llms.txt Allows customization of the work files list before display. It filters and modifies file metadata, such as excluding files older than a specified number of days. The hook takes a list of work file dictionaries and returns a filtered list. ```python import sgtk HookClass = sgtk.get_hook_baseclass() class FilterWorkFiles(HookClass): """ Hook to filter the list of work files found for the current work area. """ def execute(self, work_files, **kwargs): """ Filter or modify the work files list. :param work_files: List of dictionaries with 'work_file' key containing: - version_number: Version of the work file - name: Name of the work file - task: Associated task - description: File description - thumbnail: Thumbnail for display - modified_at: Last modified datetime - modified_by: Shotgun user dictionary :returns: Filtered list of work file dictionaries """ app = self.parent # Example: Filter out files older than 30 days from datetime import datetime, timedelta cutoff_date = datetime.now() - timedelta(days=30) filtered_files = [] for work_file_dict in work_files: work_file = work_file_dict.get("work_file", {}) modified_at = work_file.get("modified_at") if modified_at is None or modified_at > cutoff_date: filtered_files.append(work_file_dict) return filtered_files ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.