mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-01 08:24:53 +01:00
Action register to user that match session.api_user
This commit is contained in:
parent
12799f8cad
commit
9ca3d61613
4 changed files with 55 additions and 201 deletions
|
|
@ -1,8 +1,9 @@
|
|||
import os
|
||||
import logging
|
||||
import toml
|
||||
import ftrack_api
|
||||
from ftrack_action_handler.appaction import AppAction
|
||||
from avalon import io
|
||||
from avalon import io, lib
|
||||
|
||||
|
||||
os.environ['AVALON_PROJECTS'] = 'tmp'
|
||||
|
|
@ -20,6 +21,8 @@ s = ftrack_api.Session(
|
|||
def register(session):
|
||||
apps=[]
|
||||
actions = []
|
||||
icon = None
|
||||
|
||||
for project in projects:
|
||||
os.environ['AVALON_PROJECT'] = project['name']
|
||||
for app in project['config']['apps']:
|
||||
|
|
@ -27,8 +30,14 @@ def register(session):
|
|||
apps.append(app)
|
||||
|
||||
for app in apps:
|
||||
AppAction(session, app['label'], app['name']).register()
|
||||
if 'nuke' in app['name']:
|
||||
icon = "https://mbtskoudsalg.com/images/nuke-icon-png-2.png"
|
||||
elif 'maya' in app['name']:
|
||||
icon = "http://icons.iconarchive.com/icons/froyoshark/enkel/256/Maya-icon.png"
|
||||
else:
|
||||
icon = None
|
||||
|
||||
AppAction(session, app['label'], app['name'], icon).register()
|
||||
|
||||
session.event_hub.wait()
|
||||
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ class SyncToAvalon(BaseAction):
|
|||
|
||||
# set AVALON_PROJECT env
|
||||
os.environ["AVALON_PROJECT"] = entityProj["full_name"]
|
||||
os.environ["AVALON_ASSET"] = entityProj['full_name']
|
||||
|
||||
# Get apps from Ftrack / TODO Exceptions?!!!
|
||||
apps = []
|
||||
|
|
@ -87,8 +88,6 @@ class SyncToAvalon(BaseAction):
|
|||
template = {"schema": "avalon-core:inventory-1.0"}
|
||||
|
||||
# --- Create project and assets in Avalon ---
|
||||
os.environ['AVALON_ASSET'] = entityProj['full_name']
|
||||
|
||||
io.install()
|
||||
# If project don't exists -> <Create project> ELSE <Update Config>
|
||||
if (io.find_one(
|
||||
|
|
@ -98,6 +97,10 @@ class SyncToAvalon(BaseAction):
|
|||
io.update_many({'type': 'project','name': entityProj['full_name']},
|
||||
{'$set':{'config':config}})
|
||||
|
||||
# Store info about project (FtrackId)
|
||||
io.update_many({'type': 'project','name': entityProj['full_name']},
|
||||
{'$set':{'data':{'ftrackId':entityProj['id'],'entityType':entityProj.entity_type}}})
|
||||
|
||||
# Store project Id
|
||||
projectId = io.find_one({"type": "project", "name": entityProj["full_name"]})["_id"]
|
||||
if custAttrName in entityProj['custom_attributes'] and entityProj['custom_attributes'][custAttrName] is '':
|
||||
|
|
|
|||
|
|
@ -1,169 +0,0 @@
|
|||
def _discoverApplications(self):
|
||||
'''Return a list of applications that can be launched from this host.
|
||||
|
||||
An application should be of the form:
|
||||
|
||||
dict(
|
||||
'identifier': 'name_version',
|
||||
'label': 'Name',
|
||||
'variant': 'version',
|
||||
'description': 'description',
|
||||
'path': 'Absolute path to the file',
|
||||
'version': 'Version of the application',
|
||||
'icon': 'URL or name of predefined icon'
|
||||
)
|
||||
|
||||
'''
|
||||
applications = []
|
||||
|
||||
if sys.platform == 'darwin':
|
||||
prefix = ['/', 'Applications']
|
||||
|
||||
elif sys.platform == 'win32':
|
||||
prefix = ['C:\\', 'Program Files.*']
|
||||
|
||||
self.logger.debug(
|
||||
'Discovered applications:\n{0}'.format(
|
||||
pprint.pformat(applications)
|
||||
)
|
||||
)
|
||||
|
||||
return applications
|
||||
|
||||
class ApplicationLauncher(object):
|
||||
'''Launch applications described by an application store.
|
||||
|
||||
Launched applications are started detached so exiting current process will
|
||||
not close launched applications.
|
||||
|
||||
'''
|
||||
|
||||
def __init__(self, applicationStore):
|
||||
'''Instantiate launcher with *applicationStore* of applications.
|
||||
|
||||
*applicationStore* should be an instance of :class:`ApplicationStore`
|
||||
holding information about applications that can be launched.
|
||||
|
||||
'''
|
||||
super(ApplicationLauncher, self).__init__()
|
||||
self.logger = logging.getLogger(
|
||||
__name__ + '.' + self.__class__.__name__
|
||||
)
|
||||
|
||||
self.applicationStore = applicationStore
|
||||
|
||||
def launch(self, applicationIdentifier, context=None):
|
||||
'''Launch application matching *applicationIdentifier*.
|
||||
|
||||
*context* should provide information that can guide how to launch the
|
||||
application.
|
||||
|
||||
Return a dictionary of information containing:
|
||||
|
||||
success - A boolean value indicating whether application launched
|
||||
successfully or not.
|
||||
message - Any additional information (such as a failure message).
|
||||
|
||||
'''
|
||||
# Look up application.
|
||||
applicationIdentifierPattern = applicationIdentifier
|
||||
if applicationIdentifierPattern == 'hieroplayer':
|
||||
applicationIdentifierPattern += '*'
|
||||
|
||||
application = self.applicationStore.getApplication(
|
||||
applicationIdentifierPattern
|
||||
)
|
||||
|
||||
if application is None:
|
||||
return {
|
||||
'success': False,
|
||||
'message': (
|
||||
'{0} application not found.'
|
||||
.format(applicationIdentifier)
|
||||
)
|
||||
}
|
||||
|
||||
# Construct command and environment.
|
||||
command = self._getApplicationLaunchCommand(application, context)
|
||||
environment = self._getApplicationEnvironment(application, context)
|
||||
|
||||
# Environment must contain only strings.
|
||||
self._conformEnvironment(environment)
|
||||
|
||||
success = True
|
||||
message = '{0} application started.'.format(application['label'])
|
||||
|
||||
try:
|
||||
options = dict(
|
||||
env=environment,
|
||||
close_fds=True
|
||||
)
|
||||
|
||||
# Ensure that current working directory is set to the root of the
|
||||
# application being launched to avoid issues with applications
|
||||
# locating shared libraries etc.
|
||||
applicationRootPath = os.path.dirname(application['path'])
|
||||
options['cwd'] = applicationRootPath
|
||||
|
||||
# Ensure subprocess is detached so closing connect will not also
|
||||
# close launched applications.
|
||||
if sys.platform == 'win32':
|
||||
options['creationflags'] = subprocess.CREATE_NEW_CONSOLE
|
||||
else:
|
||||
options['preexec_fn'] = os.setsid
|
||||
|
||||
launchData = dict(
|
||||
command=command,
|
||||
options=options,
|
||||
application=application,
|
||||
context=context
|
||||
)
|
||||
ftrack.EVENT_HUB.publish(
|
||||
ftrack.Event(
|
||||
topic='ftrack.connect.application.launch',
|
||||
data=launchData
|
||||
),
|
||||
synchronous=True
|
||||
)
|
||||
ftrack_connect.session.get_shared_session().event_hub.publish(
|
||||
ftrack_api.event.base.Event(
|
||||
topic='ftrack.connect.application.launch',
|
||||
data=launchData
|
||||
),
|
||||
synchronous=True
|
||||
)
|
||||
|
||||
# Reset variables passed through the hook since they might
|
||||
# have been replaced by a handler.
|
||||
command = launchData['command']
|
||||
options = launchData['options']
|
||||
application = launchData['application']
|
||||
context = launchData['context']
|
||||
|
||||
self.logger.debug(
|
||||
'Launching {0} with options {1}'.format(command, options)
|
||||
)
|
||||
process = subprocess.Popen(command, **options)
|
||||
|
||||
except (OSError, TypeError):
|
||||
self.logger.exception(
|
||||
'{0} application could not be started with command "{1}".'
|
||||
.format(applicationIdentifier, command)
|
||||
)
|
||||
|
||||
success = False
|
||||
message = '{0} application could not be started.'.format(
|
||||
application['label']
|
||||
)
|
||||
|
||||
else:
|
||||
self.logger.debug(
|
||||
'{0} application started. (pid={1})'.format(
|
||||
applicationIdentifier, process.pid
|
||||
)
|
||||
)
|
||||
|
||||
return {
|
||||
'success': success,
|
||||
'message': message
|
||||
}
|
||||
67
pype/vendor/ftrack_action_handler/appaction.py
vendored
67
pype/vendor/ftrack_action_handler/appaction.py
vendored
|
|
@ -33,9 +33,9 @@ class AppAction(object):
|
|||
self._session = session
|
||||
self.label = label
|
||||
self.identifier = name
|
||||
self.icon = None
|
||||
self.variant = None
|
||||
self.description = None
|
||||
self.icon = icon
|
||||
self.variant = variant
|
||||
self.description = description
|
||||
|
||||
|
||||
@property
|
||||
|
|
@ -46,13 +46,10 @@ class AppAction(object):
|
|||
def register(self):
|
||||
'''Registers the action, subscribing the the discover and launch topics.'''
|
||||
self.session.event_hub.subscribe(
|
||||
'topic=ftrack.action.discover', self._discover
|
||||
'topic=ftrack.action.discover and source.user.username={0}'.format(
|
||||
self.session.api_user
|
||||
), self._discover
|
||||
)
|
||||
# self.session.event_hub.subscribe(
|
||||
# 'topic=ftrack.action.discover and source.user.username={0}'.format(
|
||||
# getpass.getuser()
|
||||
# ), self._discover
|
||||
# )
|
||||
|
||||
self.session.event_hub.subscribe(
|
||||
'topic=ftrack.action.launch and data.actionIdentifier={0}'.format(
|
||||
|
|
@ -96,8 +93,6 @@ class AppAction(object):
|
|||
*event* the unmodified original event
|
||||
|
||||
'''
|
||||
if len(entities) > 1:
|
||||
return False
|
||||
|
||||
entity_type, entity_id = entities[0]
|
||||
entity = session.get(entity_type, entity_id)
|
||||
|
|
@ -106,18 +101,27 @@ class AppAction(object):
|
|||
# if entity.entity_type != 'Task':
|
||||
# return False
|
||||
|
||||
ft_project = entity['project']
|
||||
# TODO Should return False if more than one entity is selected ?!!!
|
||||
# if len(entities) > 1:
|
||||
# return False
|
||||
|
||||
|
||||
ft_project = entity['project'] if (entity.entity_type != 'Project') else entity
|
||||
|
||||
os.environ['AVALON_PROJECT'] = ft_project['full_name']
|
||||
io.install()
|
||||
project = io.find_one({"type": "project", "name": ft_project['full_name']})
|
||||
io.uninstall()
|
||||
|
||||
apps = []
|
||||
for app in project['config']['apps']:
|
||||
apps.append(app['name'])
|
||||
if self.identifier not in apps:
|
||||
if project is None:
|
||||
return False
|
||||
else:
|
||||
apps = []
|
||||
for app in project['config']['apps']:
|
||||
apps.append(app['name'])
|
||||
|
||||
if self.identifier not in apps:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
|
@ -202,28 +206,35 @@ class AppAction(object):
|
|||
|
||||
'''
|
||||
# TODO Delete this line
|
||||
print("Action < {0} ({1}) > just started".format(self.label, self.identifier))
|
||||
print("Action - {0} ({1}) - just started".format(self.label, self.identifier))
|
||||
|
||||
# Get path to execute
|
||||
st_temp_path = os.environ['PYPE_STUDIO_TEMPLATES']
|
||||
os_plat = platform.system().lower()
|
||||
|
||||
# Path to folder with .bat
|
||||
# Path to folder with launchers
|
||||
path = os.path.join(st_temp_path, 'bin', os_plat)
|
||||
file = self.identifier
|
||||
# Full path to executable launcher
|
||||
execfile = None
|
||||
|
||||
''' NEED TO ADD FILE NAMES FOR OTHER SYSTEMS '''
|
||||
if os_plat == 'windows':
|
||||
file += ".bat"
|
||||
for ext in os.environ["PATHEXT"].split(os.pathsep):
|
||||
fpath = os.path.join(path.strip('"'), self.identifier + ext)
|
||||
if os.path.isfile(fpath) and os.access(fpath, os.X_OK):
|
||||
execfile = fpath
|
||||
break
|
||||
|
||||
abspath = os.path.join(path.strip('"'), file)
|
||||
|
||||
if os.path.isfile(abspath) and os.access(abspath, os.X_OK):
|
||||
os.startfile(abspath)
|
||||
if execfile is not None:
|
||||
os.startfile(execfile)
|
||||
else:
|
||||
return False
|
||||
return {
|
||||
'success': False,
|
||||
'message': "We didn't found launcher for {0}".format(self.label)
|
||||
}
|
||||
|
||||
return True
|
||||
return {
|
||||
'success': True,
|
||||
'message': "Launching {0}".format(self.label)
|
||||
}
|
||||
|
||||
def _interface(self, *args):
|
||||
interface = self.interface(*args)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue