mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-25 21:32:15 +01:00
more io usage replaced, added ignore_me variable to actions/events for ftrack server, added 'get avalon projects' function, fixed few bugs, added titles to show_interface in action handlers
This commit is contained in:
parent
ae68a41400
commit
9d50a5b8b7
10 changed files with 153 additions and 93 deletions
|
|
@ -1,8 +1,9 @@
|
|||
import os
|
||||
import toml
|
||||
import time
|
||||
from ftrack_action_handler import AppAction
|
||||
from avalon import io, lib
|
||||
from avalon import lib
|
||||
from app.api import Logger
|
||||
from pype import lib as pypelib
|
||||
|
||||
log = Logger.getLogger(__name__)
|
||||
|
||||
|
|
@ -28,8 +29,11 @@ def registerApp(app, session):
|
|||
|
||||
apptoml = toml.load(abspath)
|
||||
|
||||
''' REQUIRED '''
|
||||
executable = apptoml['executable']
|
||||
label = apptoml.get('ftrack_label', app['label'])
|
||||
|
||||
''' OPTIONAL '''
|
||||
label = apptoml.get('ftrack_label', app.get('label', name))
|
||||
icon = apptoml.get('ftrack_icon', None)
|
||||
description = apptoml.get('description', None)
|
||||
|
||||
|
|
@ -40,17 +44,7 @@ def registerApp(app, session):
|
|||
|
||||
|
||||
def register(session):
|
||||
# set avalon environ - they just must exist
|
||||
os.environ['AVALON_PROJECT'] = ''
|
||||
os.environ['AVALON_ASSET'] = ''
|
||||
os.environ['AVALON_SILO'] = ''
|
||||
# Get all projects from Avalon DB
|
||||
try:
|
||||
io.install()
|
||||
projects = sorted(io.projects(), key=lambda x: x['name'])
|
||||
io.uninstall()
|
||||
except Exception as e:
|
||||
log.error(e)
|
||||
projects = pypelib.get_all_avalon_projects()
|
||||
|
||||
apps = []
|
||||
appNames = []
|
||||
|
|
@ -65,5 +59,6 @@ def register(session):
|
|||
for app in apps:
|
||||
try:
|
||||
registerApp(app, session)
|
||||
time.sleep(0.05)
|
||||
except Exception as e:
|
||||
log.warning("'{0}' - not proper App ({1})".format(app['name'], e))
|
||||
|
|
|
|||
|
|
@ -147,7 +147,6 @@ class SyncToAvalon(BaseAction):
|
|||
)
|
||||
|
||||
if 'errors' in result and len(result['errors']) > 0:
|
||||
print('error')
|
||||
items = []
|
||||
for error in result['errors']:
|
||||
for key, message in error.items():
|
||||
|
|
@ -162,10 +161,12 @@ class SyncToAvalon(BaseAction):
|
|||
self.log.error(
|
||||
'{}: {}'.format(key, message)
|
||||
)
|
||||
title = 'Hey You! Few Errors were raised! (*look below*)'
|
||||
|
||||
job['status'] = 'failed'
|
||||
session.commit()
|
||||
self.show_interface(event, items)
|
||||
|
||||
self.show_interface(event, items, title)
|
||||
return {
|
||||
'success': False,
|
||||
'message': "Sync to avalon FAILED"
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ import sys
|
|||
import json
|
||||
import base64
|
||||
|
||||
|
||||
ignore_me = True
|
||||
# sys.path.append(os.path.dirname(os.path.dirname(__file__)))
|
||||
# from ftrack_kredenc.lucidity.vendor import yaml
|
||||
# from ftrack_kredenc import lucidity
|
||||
|
|
|
|||
|
|
@ -4,12 +4,16 @@ import os
|
|||
import sys
|
||||
import platform
|
||||
import ftrack_api
|
||||
from avalon import io, lib
|
||||
from avalon import lib
|
||||
import acre
|
||||
|
||||
from pype.ftrack import ftrack_utils
|
||||
from pype import api as pype
|
||||
|
||||
|
||||
ignore_me = True
|
||||
|
||||
|
||||
class AppAction(object):
|
||||
'''Custom Action base class
|
||||
|
||||
|
|
@ -122,33 +126,20 @@ class AppAction(object):
|
|||
entity = session.get(entity_type, entity_id)
|
||||
|
||||
# TODO Should return False if not TASK ?!!!
|
||||
if entity.entity_type != 'Task':
|
||||
return False
|
||||
|
||||
# TODO Should return False if more than one entity is selected ?!!!
|
||||
if len(entities) > 1:
|
||||
if (
|
||||
len(entities) > 1 or
|
||||
entity.entity_type.lower() != 'task'
|
||||
):
|
||||
return False
|
||||
|
||||
ft_project = entity
|
||||
if (entity.entity_type != 'Project'):
|
||||
ft_project = entity['project']
|
||||
ft_project = entity['project']
|
||||
|
||||
silo = ""
|
||||
if 'ancestors' in entity:
|
||||
for ancestor in entity['ancestors']:
|
||||
silo = ancestor['name']
|
||||
break
|
||||
|
||||
os.environ['AVALON_PROJECT'] = ft_project['full_name']
|
||||
os.environ['AVALON_ASSET'] = entity['name']
|
||||
os.environ['AVALON_SILO'] = silo
|
||||
|
||||
io.install()
|
||||
avalon_project = io.find_one({
|
||||
"type": "project",
|
||||
"name": ft_project['full_name']
|
||||
database = ftrack_utils.get_avalon_database()
|
||||
project_name = ft_project['full_name']
|
||||
avalon_project = database[project_name].find_one({
|
||||
"type": "project"
|
||||
})
|
||||
io.uninstall()
|
||||
|
||||
if avalon_project is None:
|
||||
return False
|
||||
|
|
@ -249,24 +240,37 @@ class AppAction(object):
|
|||
|
||||
entity, id = entities[0]
|
||||
entity = session.get(entity, id)
|
||||
project_name = entity['project']['full_name']
|
||||
|
||||
database = ftrack_utils.get_avalon_database()
|
||||
|
||||
# Get current environments
|
||||
env_list = [
|
||||
'AVALON_PROJECT',
|
||||
'AVALON_SILO',
|
||||
'AVALON_ASSET',
|
||||
'AVALON_TASK',
|
||||
'AVALON_APP',
|
||||
'AVALON_APP_NAME'
|
||||
]
|
||||
env_origin = {}
|
||||
for env in env_list:
|
||||
env_origin[env] = os.environ.get(env, None)
|
||||
|
||||
# set environments for Avalon
|
||||
os.environ["AVALON_PROJECT"] = entity['project']['full_name']
|
||||
os.environ["AVALON_PROJECT"] = project_name
|
||||
os.environ["AVALON_SILO"] = entity['ancestors'][0]['name']
|
||||
os.environ["AVALON_ASSET"] = entity['parent']['name']
|
||||
os.environ["AVALON_TASK"] = entity['name']
|
||||
os.environ["AVALON_APP"] = self.identifier.split("_")[0]
|
||||
os.environ["AVALON_APP_NAME"] = self.identifier
|
||||
|
||||
os.environ["FTRACK_TASKID"] = id
|
||||
|
||||
anatomy = pype.Anatomy
|
||||
io.install()
|
||||
hierarchy = io.find_one({
|
||||
hierarchy = database[project_name].find_one({
|
||||
"type": 'asset',
|
||||
"name": entity['parent']['name']
|
||||
})['data']['parents']
|
||||
io.uninstall()
|
||||
|
||||
if hierarchy:
|
||||
hierarchy = os.path.join(*hierarchy)
|
||||
|
||||
|
|
@ -384,6 +388,10 @@ class AppAction(object):
|
|||
self.log.info('Starting timer for task: ' + task['name'])
|
||||
user.start_timer(task, force=True)
|
||||
|
||||
# Set origin avalon environments
|
||||
for key, value in env_origin.items():
|
||||
os.environ[key] = value
|
||||
|
||||
return {
|
||||
'success': True,
|
||||
'message': "Launching {0}".format(self.label)
|
||||
|
|
@ -729,7 +737,7 @@ class BaseAction(object):
|
|||
|
||||
return result
|
||||
|
||||
def show_interface(self, event, items):
|
||||
def show_interface(self, event, items, title=''):
|
||||
"""
|
||||
Shows interface to user who triggered event
|
||||
- 'items' must be list containing Ftrack interface items
|
||||
|
|
@ -744,7 +752,8 @@ class BaseAction(object):
|
|||
topic='ftrack.action.trigger-user-interface',
|
||||
data=dict(
|
||||
type='widget',
|
||||
items=items
|
||||
items=items,
|
||||
title=title
|
||||
),
|
||||
target=target
|
||||
),
|
||||
|
|
|
|||
|
|
@ -158,7 +158,6 @@ class Sync_To_Avalon(BaseAction):
|
|||
)
|
||||
|
||||
if 'errors' in result and len(result['errors']) > 0:
|
||||
print('error')
|
||||
items = []
|
||||
for error in result['errors']:
|
||||
for key, message in error.items():
|
||||
|
|
@ -173,10 +172,12 @@ class Sync_To_Avalon(BaseAction):
|
|||
self.log.error(
|
||||
'{}: {}'.format(key, message)
|
||||
)
|
||||
title = 'Hey You! Few Errors were raised! (*look below*)'
|
||||
|
||||
job['status'] = 'failed'
|
||||
session.commit()
|
||||
self.show_interface(event, items)
|
||||
|
||||
self.show_interface(event, items, title)
|
||||
return {
|
||||
'success': False,
|
||||
'message': "Sync to avalon FAILED"
|
||||
|
|
|
|||
|
|
@ -86,7 +86,6 @@ class Sync_to_Avalon(BaseEvent):
|
|||
custom_attributes=custom_attributes
|
||||
)
|
||||
if 'errors' in result and len(result['errors']) > 0:
|
||||
print('error')
|
||||
items = []
|
||||
for error in result['errors']:
|
||||
for key, message in error.items():
|
||||
|
|
@ -101,9 +100,9 @@ class Sync_to_Avalon(BaseEvent):
|
|||
self.log.error(
|
||||
'{}: {}'.format(key, message)
|
||||
)
|
||||
|
||||
session.commit()
|
||||
self.show_interface(event, items)
|
||||
title = 'Hey You! You raised few Errors! (*look below*)'
|
||||
self.show_interface(event, items, title)
|
||||
return
|
||||
|
||||
if avalon_project is None:
|
||||
|
|
@ -122,7 +121,8 @@ class Sync_to_Avalon(BaseEvent):
|
|||
'name': 'error',
|
||||
'value': ftrack_message
|
||||
}]
|
||||
self.show_interface(event, items)
|
||||
title = 'Hey You! Unknown Error has been raised! (*look below*)'
|
||||
self.show_interface(event, items, title)
|
||||
self.log.error(message)
|
||||
|
||||
return
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ class BaseEvent(object):
|
|||
on_error='ignore'
|
||||
)
|
||||
|
||||
def show_interface(self, event, items):
|
||||
def show_interface(self, event, items, title=''):
|
||||
"""
|
||||
Shows interface to user who triggered event
|
||||
- 'items' must be list containing Ftrack interface items
|
||||
|
|
@ -153,7 +153,8 @@ class BaseEvent(object):
|
|||
topic='ftrack.action.trigger-user-interface',
|
||||
data=dict(
|
||||
type='widget',
|
||||
items=items
|
||||
items=items,
|
||||
title=title
|
||||
),
|
||||
target=target
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import sys
|
||||
import os
|
||||
import json
|
||||
import threading
|
||||
|
|
@ -6,6 +5,7 @@ import time
|
|||
import ftrack_api
|
||||
from app import style
|
||||
from app.vendor.Qt import QtCore, QtGui, QtWidgets
|
||||
|
||||
from pype.ftrack import credentials, login_dialog as login_dialog
|
||||
|
||||
from pype.vendor.pynput import mouse, keyboard
|
||||
|
|
@ -21,7 +21,6 @@ log = pype.Logger.getLogger(__name__, "ftrack")
|
|||
|
||||
|
||||
class FtrackRunner:
|
||||
|
||||
def __init__(self, main_parent=None, parent=None):
|
||||
|
||||
self.parent = parent
|
||||
|
|
@ -86,7 +85,9 @@ class FtrackRunner:
|
|||
# Actions part
|
||||
def start_action_server(self):
|
||||
if self.thread_action_server is None:
|
||||
self.thread_action_server = threading.Thread(target=self.set_action_server)
|
||||
self.thread_action_server = threading.Thread(
|
||||
target=self.set_action_server
|
||||
)
|
||||
self.thread_action_server.daemon = True
|
||||
self.thread_action_server.start()
|
||||
|
||||
|
|
@ -95,7 +96,14 @@ class FtrackRunner:
|
|||
self.set_menu_visibility()
|
||||
|
||||
def set_action_server(self):
|
||||
self.action_server.run_server()
|
||||
try:
|
||||
self.action_server.run_server()
|
||||
except Exception:
|
||||
msg = 'Ftrack Action server crashed! Please try to start again.'
|
||||
log.error(msg)
|
||||
# TODO show message to user
|
||||
self.bool_action_server = False
|
||||
self.set_menu_visibility()
|
||||
|
||||
def reset_action_server(self):
|
||||
self.stop_action_server()
|
||||
|
|
@ -123,11 +131,19 @@ class FtrackRunner:
|
|||
|
||||
# Actions - server
|
||||
self.smActionS = self.menu.addMenu("Action server")
|
||||
self.aRunActionS = QtWidgets.QAction("Run action server", self.smActionS)
|
||||
|
||||
self.aRunActionS = QtWidgets.QAction(
|
||||
"Run action server", self.smActionS
|
||||
)
|
||||
self.aResetActionS = QtWidgets.QAction(
|
||||
"Reset action server", self.smActionS
|
||||
)
|
||||
self.aStopActionS = QtWidgets.QAction(
|
||||
"Stop action server", self.smActionS
|
||||
)
|
||||
|
||||
self.aRunActionS.triggered.connect(self.start_action_server)
|
||||
self.aResetActionS = QtWidgets.QAction("Reset action server", self.smActionS)
|
||||
self.aResetActionS.triggered.connect(self.reset_action_server)
|
||||
self.aStopActionS = QtWidgets.QAction("Stop action server", self.smActionS)
|
||||
self.aStopActionS.triggered.connect(self.stop_action_server)
|
||||
|
||||
self.smActionS.addAction(self.aRunActionS)
|
||||
|
|
@ -168,12 +184,19 @@ class FtrackRunner:
|
|||
self.start_timer_thread()
|
||||
|
||||
def start_timer_thread(self):
|
||||
if self.thread_timer is None:
|
||||
self.thread_timer = FtrackEventsThread(self)
|
||||
self.bool_timer_event = True
|
||||
self.thread_timer.signal_timer_started.connect(self.timer_started)
|
||||
self.thread_timer.signal_timer_stopped.connect(self.timer_stopped)
|
||||
self.thread_timer.start()
|
||||
try:
|
||||
if self.thread_timer is None:
|
||||
self.thread_timer = FtrackEventsThread(self)
|
||||
self.bool_timer_event = True
|
||||
self.thread_timer.signal_timer_started.connect(
|
||||
self.timer_started
|
||||
)
|
||||
self.thread_timer.signal_timer_stopped.connect(
|
||||
self.timer_stopped
|
||||
)
|
||||
self.thread_timer.start()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def stop_timer_thread(self):
|
||||
try:
|
||||
|
|
@ -188,9 +211,15 @@ class FtrackRunner:
|
|||
def start_countdown_thread(self):
|
||||
if self.thread_timer_coundown is None:
|
||||
self.thread_timer_coundown = CountdownThread(self)
|
||||
self.thread_timer_coundown.signal_show_question.connect(self.show_widget_timer)
|
||||
self.thread_timer_coundown.signal_send_time.connect(self.change_count_widget)
|
||||
self.thread_timer_coundown.signal_stop_timer.connect(self.timer_stop)
|
||||
self.thread_timer_coundown.signal_show_question.connect(
|
||||
self.show_widget_timer
|
||||
)
|
||||
self.thread_timer_coundown.signal_send_time.connect(
|
||||
self.change_count_widget
|
||||
)
|
||||
self.thread_timer_coundown.signal_stop_timer.connect(
|
||||
self.timer_stop
|
||||
)
|
||||
self.thread_timer_coundown.start()
|
||||
|
||||
def stop_countdown_thread(self):
|
||||
|
|
@ -255,7 +284,9 @@ class FtrackEventsThread(QtCore.QThread):
|
|||
def run(self):
|
||||
self.timer_session = ftrack_api.Session(auto_connect_event_hub=True)
|
||||
self.timer_session.event_hub.subscribe(
|
||||
'topic=ftrack.update and source.user.username={}'.format(self.username),
|
||||
'topic=ftrack.update and source.user.username={}'.format(
|
||||
self.username
|
||||
),
|
||||
self.event_handler)
|
||||
|
||||
user_query = 'User where username is "{}"'.format(self.username)
|
||||
|
|
@ -273,7 +304,7 @@ class FtrackEventsThread(QtCore.QThread):
|
|||
try:
|
||||
if event['data']['entities'][0]['objectTypeId'] != 'timer':
|
||||
return
|
||||
except:
|
||||
except Exception:
|
||||
return
|
||||
|
||||
new = event['data']['entities'][0]['changes']['start']['new']
|
||||
|
|
@ -301,12 +332,6 @@ class FtrackEventsThread(QtCore.QThread):
|
|||
|
||||
def ftrack_restart_timer(self):
|
||||
try:
|
||||
last_task = None
|
||||
if "FTRACK_LAST_TASK_ID" in os.environ:
|
||||
task_id = os.environ["FTRACK_LAST_TASK_ID"]
|
||||
query = 'Task where id is {}'.format(task_id)
|
||||
last_task = self.timer_session.query(query).one()
|
||||
|
||||
if (self.last_task is not None) and (self.user is not None):
|
||||
self.user.start_timer(self.last_task)
|
||||
self.timer_session.commit()
|
||||
|
|
@ -386,7 +411,11 @@ class CountdownThread(QtCore.QThread):
|
|||
json_dict = json.load(data_file)
|
||||
data = json_dict['timer']
|
||||
except Exception as e:
|
||||
msg = 'Loading "Ftrack Config file" Failed. Please check log for more information. Times are set to default.'
|
||||
msg = (
|
||||
'Loading "Ftrack Config file" Failed.'
|
||||
' Please check log for more information.'
|
||||
' Times are set to default.'
|
||||
)
|
||||
log.warning("{} - {}".format(msg, str(e)))
|
||||
|
||||
data = self.validate_timer_values(data)
|
||||
|
|
@ -485,15 +514,17 @@ class StopTimer(QtWidgets.QWidget):
|
|||
|
||||
def _main(self):
|
||||
self.main = QtWidgets.QVBoxLayout()
|
||||
self.main.setObjectName("main")
|
||||
self.main.setObjectName('main')
|
||||
|
||||
self.form = QtWidgets.QFormLayout()
|
||||
self.form.setContentsMargins(10, 15, 10, 5)
|
||||
self.form.setObjectName("form")
|
||||
self.form.setObjectName('form')
|
||||
|
||||
msg_info = "You didn't work for a long time."
|
||||
msg_question = "Would you like to stop Ftrack timer?"
|
||||
msg_stopped = "Your Ftrack timer was stopped. Do you want to start again?"
|
||||
msg_info = 'You didn\'t work for a long time.'
|
||||
msg_question = 'Would you like to stop Ftrack timer?'
|
||||
msg_stopped = (
|
||||
'Your Ftrack timer was stopped. Do you want to start again?'
|
||||
)
|
||||
|
||||
self.lbl_info = QtWidgets.QLabel(msg_info)
|
||||
self.lbl_info.setFont(self.font)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import os
|
||||
import re
|
||||
from pype import lib
|
||||
from avalon import io, schema
|
||||
from pype.lib import get_avalon_database
|
||||
from avalon import schema
|
||||
from bson.objectid import ObjectId
|
||||
from pype.ftrack.ftrack_utils import ftrack_utils
|
||||
from avalon.vendor import jsonschema
|
||||
|
|
@ -11,12 +12,6 @@ ValidationError = jsonschema.ValidationError
|
|||
log = Logger.getLogger(__name__)
|
||||
|
||||
|
||||
def get_avalon_database():
|
||||
if io._database is None:
|
||||
io.install()
|
||||
return io._database
|
||||
|
||||
|
||||
def get_ca_mongoid():
|
||||
# returns name of Custom attribute that stores mongo_id
|
||||
return 'avalon_mongo_id'
|
||||
|
|
@ -213,6 +208,10 @@ def import_to_avalon(
|
|||
errors.append({'Entity name duplication': msg})
|
||||
output['errors'] = errors
|
||||
return output
|
||||
|
||||
# Store new ID (in case that asset was removed from DB)
|
||||
else:
|
||||
mongo_id = avalon_asset['_id']
|
||||
else:
|
||||
if avalon_asset['name'] != entity['name']:
|
||||
if silo is None or changeability_check_childs(entity) is False:
|
||||
|
|
@ -388,7 +387,7 @@ def get_data(entity, session, custom_attributes):
|
|||
parentId = None
|
||||
|
||||
for parent in parents:
|
||||
parentId = database[project_name](
|
||||
parentId = database[project_name].find_one(
|
||||
{'type': 'asset', 'name': parName}
|
||||
)['_id']
|
||||
if parent['parent'].entity_type != 'project' and parentId is None:
|
||||
|
|
|
|||
21
pype/lib.py
21
pype/lib.py
|
|
@ -372,3 +372,24 @@ def get_avalon_project_template():
|
|||
def get_avalon_asset_template_schema():
|
||||
schema = "avalon-core:asset-2.0"
|
||||
return schema
|
||||
|
||||
|
||||
def get_avalon_database():
|
||||
if io._database is None:
|
||||
project = os.environ.get('AVALON_PROJECT', '')
|
||||
asset = os.environ.get('AVALON_ASSET', '')
|
||||
silo = os.environ.get('AVALON_SILO', '')
|
||||
os.environ['AVALON_PROJECT'] = project
|
||||
os.environ['AVALON_ASSET'] = asset
|
||||
os.environ['AVALON_SILO'] = silo
|
||||
io.install()
|
||||
return io._database
|
||||
|
||||
|
||||
def get_all_avalon_projects():
|
||||
db = get_avalon_database()
|
||||
project_names = db.collection_names()
|
||||
projects = []
|
||||
for name in project_names:
|
||||
projects.append(db[name].find_one({'type': 'project'}))
|
||||
return projects
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue