Skip to main content

Event Hooks

Event hooks in Anchorpoint allow you to respond to specific events that happen within the application. Every time a certain event occurs, a Python callback function is triggered automatically. This enables you to create reactive workflows and automate tasks based on user interactions and system changes.

Usage

To implement event hooks, simply define callback functions with specific names within your action's Python script. You don't need to register these functions explicitly - Anchorpoint will automatically detect and call them when the corresponding events occur.

import anchorpoint

def on_timeout(ctx: anchorpoint.Context):
# This code will be automatically executed once every minute
print("timeout callback")

def on_folder_opened(ctx: anchorpoint.Context):
# This code will be executed when user navigates to a folder
print(f"folder opened: {ctx.path}")

if __name__ == "__main__":
# This code will be executed when the user triggers the action manually
print("Action invoked!")

Important: When mixing event hooks with regular action code, make sure to guard your normal action code using if __name__ == "__main__": to prevent it from executing when the script is loaded for hooks.

Application Events

  • on_timeout(ctx) Called once every minute automatically. Useful for periodic checks, background tasks, or monitoring file system state.

    Arguments

    • ctx (class: Context): Current context with browser state
  • on_folder_opened(ctx) Called whenever the user navigates to a folder in Anchorpoint. Useful for folder-specific initialization or validation.

    Arguments

    • ctx (class: Context): Current context with the opened folder path
  • on_project_directory_changed(ctx) Called when any change is detected within the active project directory. Triggered by file modifications, additions, deletions, etc. Only works for the currently active project in Anchorpoint.

    Arguments

    • ctx (class: Context): Current context of the active project
  • on_application_started(ctx) Called once for each workspace when Anchorpoint starts up. Useful for initialization routines or startup checks.

    Arguments

    • ctx (class: Context): Context for the starting workspace
  • on_application_closing(ctx) Called just before Anchorpoint closes. Useful for cleanup tasks or saving state.

    Arguments

    • ctx (class: Context): Current context before shutdown

Task Events

  • on_task_created(task_id, source, ctx) Called when a new task is created.

    Arguments

    • task_id (str): ID of the newly created task
    • source (class: ChangeSource): Source of the change (You, Action, Other)
    • ctx (class: Context): Current context
  • on_task_changed(task_id, source, ctx) Called when an existing task is modified.

    Arguments

    • task_id (str): ID of the modified task
    • source (class: ChangeSource): Source of the change (You, Action, Other)
    • ctx (class: Context): Current context
  • on_task_removed(task_id, source, ctx) Called when a task is deleted.

    Arguments

    • task_id (str): ID of the deleted task
    • source (class: ChangeSource): Source of the change (You, Action, Other)
    • ctx (class: Context): Current context

Attribute Events

  • on_attributes_changed(parent_path, attributes, ctx) Called when attributes are modified on files, folders, or tasks. Provides detailed information about what changed.

    Arguments

    • parent_path (str): Path of the parent object containing the changed attributes
    • attributes (List[AttributeChange]): List of attribute changes
    • ctx (class: Context): Current context

AttributeChange Class

  • AttributeChange Represents a value change of an attribute. Provides information about what changed, including the old and new values, and the source of the change.

Properties

  • path (str): Path of the object where the attribute changed (None for tasks).
  • task_id (str): ID of the task where the attribute changed (None for files/folders).
  • object_type (class: ObjectType): Type of object (file, folder, or task).
  • name (str): Name of the changed attribute.
  • type (class: AttributeType): Type of the attribute (text, rating, tag, etc.).
  • value (Any): New value of the attribute.
  • old_value (Any): Previous value of the attribute.
  • source (class: ChangeSource): Source of the change.
  • source_value (str): Client name for "Other" source changes.

ChangeSource Enumeration

  • ChangeSource Enumeration that indicates who made a change to an attribute or task. Used to identify the source of modifications for proper handling and filtering.

Values

  • ChangeSource.You (enum): The change was made by yourself
  • ChangeSource.Action (enum): The change was made by an action on your machine
  • ChangeSource.Other (enum): The change was made by someone else

Action Control Events

  • on_is_action_enabled(path, type, ctx) Special hook called to determine if an action should be shown to the user. Must be enabled in YAML configuration: register: folder: enable: script_with_hook.py

    Arguments

    • path (str): Path to check (may differ from ctx.path)
    • type (class: Type): Type of the action being checked
    • ctx (class: Context): Current browser context

    Returns (bool): True if action should be enabled, False otherwise

Examples

Periodic Monitoring

import anchorpoint
import os
from datetime import datetime

def on_timeout(ctx: anchorpoint.Context):
"""Monitor project for large files every minute"""
if not ctx.project_id:
return

api = anchorpoint.get_api()
large_files = []

# Check for files larger than 100MB in current project
for root, dirs, files in os.walk(ctx.path):
for file in files:
file_path = os.path.join(root, file)
if os.path.getsize(file_path) > 100 * 1024 * 1024: # 100MB
large_files.append(file_path)

# Tag large files
for file_path in large_files:
api.attributes.set_attribute_value(file_path, "Size Warning", "Large File")
api.attributes.set_attribute_value(file_path, "Last Checked", datetime.now())

if __name__ == "__main__":
print("Large file monitor action invoked manually")

Folder Navigation Tracking

import anchorpoint
import apsync
from datetime import datetime

def on_folder_opened(ctx: anchorpoint.Context):
"""Track folder access and set last visited timestamp"""
api = anchorpoint.get_api()

# Set last visited attribute on folder
api.attributes.set_attribute_value(ctx.path, "Last Visited", datetime.now())
api.attributes.set_attribute_value(ctx.path, "Visited By", ctx.username)

# Check if this is a project folder
project = api.get_project()
if project and ctx.path == project.path:
print(f"Project {project.name} accessed by {ctx.username}")

if __name__ == "__main__":
print("Folder tracking action invoked")

Task Workflow Automation

import anchorpoint

def on_task_created(task_id: str, source: anchorpoint.ChangeSource, ctx: anchorpoint.Context):
"""Automatically set up new tasks with default attributes"""
if source == anchorpoint.ChangeSource.You: # Only for tasks created by the user
api = anchorpoint.get_api()
task = api.tasks.get_task_by_id(task_id)

if task:
# Set default attributes for new tasks
api.attributes.set_attribute_value(f"task:{task_id}", "Status", "Not Started")
api.attributes.set_attribute_value(f"task:{task_id}", "Priority", "Medium")
api.attributes.set_attribute_value(f"task:{task_id}", "Created By", ctx.username)

print(f"Task '{task.name}' initialized with default attributes")

def on_task_changed(task_id: str, source: anchorpoint.ChangeSource, ctx: anchorpoint.Context):
"""React to task changes"""
if source != anchorpoint.ChangeSource.Action: # Avoid infinite loops
api = anchorpoint.get_api()
task = api.tasks.get_task_by_id(task_id)

# Log task changes
print(f"Task '{task.name}' was modified by {source.name}")

if __name__ == "__main__":
print("Task workflow automation loaded")

Attribute Change Monitoring

import anchorpoint

def on_attributes_changed(parent_path: str, attributes: list[anchorpoint.AttributeChange], ctx: anchorpoint.Context):
"""Monitor and react to attribute changes"""
api = anchorpoint.get_api()

for attribute in attributes:
print(f"Attribute '{attribute.name}' changed from '{attribute.old_value}' to '{attribute.value}'")

# Handle task attributes
if attribute.task_id:
task = api.tasks.get_task_by_id(attribute.task_id)
print(f"Task '{task.name}' attribute changed")

# Auto-assign reviewer when status changes to "Review"
if attribute.name == "Status" and attribute.value == "Review":
api.attributes.set_attribute_value(f"task:{attribute.task_id}", "Reviewer", "lead@company.com")

# Handle file/folder attributes
else:
print(f"File/folder '{attribute.path}' attribute changed")

# Auto-create backup when marked as "Final"
if attribute.name == "Version" and attribute.value == "Final":
backup_path = attribute.path + ".backup"
# Implementation would copy file to backup location
api.attributes.set_attribute_value(backup_path, "Backup Of", attribute.path)

if __name__ == "__main__":
print("Attribute monitoring loaded")

Conditional Action Enabling

import anchorpoint
import os

def on_is_action_enabled(path: str, type: anchorpoint.Type, ctx: anchorpoint.Context) -> bool:
"""Enable action only for specific conditions"""

# Enable only in "shots" folders
if "shots" in path.lower():
return True

# Enable for video files
video_extensions = ['.mp4', '.mov', '.avi', '.mkv']
if any(path.lower().endswith(ext) for ext in video_extensions):
return True

# Enable if file has specific attribute
api = anchorpoint.get_api()
try:
status = api.attributes.get_attribute_value(path, "Render Status")
return status == "Ready"
except:
return False

if __name__ == "__main__":
print("Conditional action executed")