Action register to user that match session.api_user

This commit is contained in:
Jakub Trllo 2018-10-26 12:19:37 +02:00
parent 12799f8cad
commit 9ca3d61613
4 changed files with 55 additions and 201 deletions

View file

@ -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()

View file

@ -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 '':

View file

@ -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
}

View file

@ -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)