mrv.maya
Covered: 180 lines
Missed: 96 lines
Skipped 203 lines
Percent: 65 %
  2
""" Inialize the mrv.maya sub-system and startup maya as completely as possible or configured """
  3
import os, sys
  4
import mrv
  5
from mrv import init_modules
  6
from mrv.util import capitalize, DAGTree, PipeSeparatedFile
  7
from mrv.exc import MRVError
  8
from mrv.path import make_path
  9
from mrv.cmd.base import maya_to_py_version_map
 11
from itertools import chain
 12
import logging
 13
log = logging.getLogger("mrv.maya")
 16
if not hasattr( sys,"_dataTypeIdToTrackingDictMap" ):
 17
	sys._dataTypeIdToTrackingDictMap = dict()			 # DataTypeId : tracking dict
 20
__all__ = ("registerPluginDataTrackingDict", )
 28
def registerPluginDataTrackingDict( dataTypeID, trackingDict ):
 29
	"""Using the given dataTypeID and tracking dict, nt.PluginData can return
 30
	self pointers belonging to an MPxPluginData instance as returned by MFnPluginData.
 31
	Call this method to register your PluginData information to the mrv system.
 32
	Afterwards you can extract the self pointer using plug.masData().data()"""
 33
	sys._dataTypeIdToTrackingDictMap[ dataTypeID.id() ] = trackingDict
 39
def initializeNewMayaRelease( ):
 40
	"""This method should be called once a new maya release is encountered. It will
 41
	initialize and update the database as well as possible, and give instructions 
 42
	on what to do next.
 44
	:note: Will not run if any user setup is performed as we need a clean maya 
 45
	without any plugins loaded.
 46
	:raise EnvironmentError: if the current maya version has already been initialized
 47
	or if the user setup was executed"""
 48
	if int(os.environ.get('MRV_STANDALONE_AUTOLOAD_PLUGINS', 0)) or \
 49
		int(os.environ.get('MRV_STANDALONE_RUN_USER_SETUP', 0)):
 50
		raise EnvironmentError("Cannot operate if custom user setup was performed")
 53
	import env
 54
	import mdb
 56
	nodeshf = mdb.nodeHierarchyFile()
 57
	app_version = env.appVersion()[0]
 58
	if nodeshf.isfile():
 59
		raise EnvironmentError("Maya version %g already initialized as hierarchy file at %s does already exist" % (app_version, nodeshf))
 65
	mdb.writeMfnDBCacheFiles()
 72
	dagTree, typeToMFnList = mdb.generateNodeHierarchy()
 73
	dagTree.to_hierarchy_file('_root_', mdb.nodeHierarchyFile())
 77
	fp = open(mdb.cacheFilePath('nodeTypeToMfnCls', 'map'), 'wb')
 78
	mla = reduce(max, (len(t[0]) for t in typeToMFnList))
 79
	mlb = reduce(max, (len(t[1]) for t in typeToMFnList))
 81
	psf = PipeSeparatedFile(fp)
 82
	psf.beginWriting((mla, mlb))
 83
	for token in typeToMFnList:
 84
		psf.writeTokens(token)
 86
	fp.close()
 91
	print >> sys.stderr, "1. git status might reveals new MFnFunction sets as untracked files - check the new methods and possibly define aliases (or delete them wiht 'x')"
 92
	print >> sys.stderr, "2. Check the 'whats new' part of the maya docs for important API changes and possibly incorporate them into the code"
 93
	print >> sys.stderr, "3. run 'tmrv %g' and fix possibly breaking tests or the code being tested" % app_version
 94
	print >> sys.stderr, "4. run 'tmrvr' to assure all maya versions are still working - ideally on all platforms."
 95
	print >> sys.stderr, "5. run the UI tests and assure that they don't fail"
 96
	print >> sys.stderr, "6. Commit and push your changes - you are done"
102
def dag_tree_from_tuple_list( tuplelist ):
103
	""":return: DagTree from list of tuples [ (level,name),...], where level specifies
104
	the level of items in the dag.
105
	:note: there needs to be only one root node which should be first in the list
106
	:return: `DagTree` item allowing to easily query the hierarchy """
107
	tree = None
108
	lastparent = None
109
	lastchild = None
110
	lastlevel = 0
112
	for no,item in enumerate( tuplelist ):
113
		level, name = item
115
		if level == 0:
116
			if tree != None:
117
				raise MRVError( "DAG tree must currently be rooted - thus there must only be one root node, found another: " + name )
118
			else:
119
				tree = DAGTree(  )		# create root
120
				tree.add_node( name )
121
				lastparent = name
122
				lastchild = name
123
				continue
125
		direction = level - lastlevel
126
		if direction > 1:
127
			raise MRVError( "Can only change by one down the dag, changed by %i in item %s" % ( direction, str( item ) ) )
129
		lastlevel = level
130
		if direction == 0:
131
			pass
132
		elif direction == 1 :
133
			lastparent = lastchild
134
		elif direction == -1:
135
			lastparent = tree.parent( lastparent )
136
		elif direction < -1:		# we go many parents back, find the parent at level
137
			lastparent = list( tree.parent_iter( lastparent ) )[ -level ]
139
		tree.add_edge( lastparent, name )
140
		lastchild = name
143
	return tree
145
def tuple_list_from_file( filepath ):
146
	"""Create a tuple hierarchy list from the file at the given path
147
	:return: tuple list suitable for dag_tree_from_tuple_list"""
148
	lines = make_path( filepath ).lines( retain = False )
150
	hierarchytuples = list()
152
	for no,line in enumerate( lines ):
153
		item = ( line.count( '\t' ), line.lstrip( '\t' ) )
154
		hierarchytuples.append( item )
156
	return hierarchytuples
158
def initWrappers( mdict, types, metacreatorcls, force_creation = False ):
159
	""" Create standin classes that will create the actual class once creation is
160
	requested.
161
	:param mdict: module dictionary object from which the latter classes will be imported from, 
162
	can be obtained using ``globals()`` in the module
163
	:param types: iterable containing the names of classnames ( they will be capitalized
164
	as classes must begin with a capital letter )"""
165
	from mrv.maya.util import StandinClass
168
	standin_instances = list()
169
	for uitype in types:
170
		clsname = capitalize( uitype )
173
		if clsname in mdict:
174
			continue
176
		standin = StandinClass( clsname, metacreatorcls )
177
		mdict[ clsname ] = standin
179
		if force_creation:
180
			standin_instances.append(standin)
185
	for standin in standin_instances:
186
		standin.createCls( )
188
def move_vars_to_environ( ):
189
	"""Move the maya vars as set in the shell into the os.environ to make them available to python"""
190
	import maya.cmds as cmds
191
	import subprocess
192
	envcmd = "env"
194
	if cmds.about( nt=1 ):
195
		envcmd = "set"
197
	p = subprocess.Popen( envcmd, shell=True, stdout=subprocess.PIPE )
199
	for line in p.stdout:
200
		try:
201
			var,value = line.split("=", 1)
202
		except:
203
			continue
204
		else:
205
			os.environ[ var ] = value.strip()
217
def init_system( ):
218
	"""
219
	Check if we are suited to import the maya namespace and try to set it
220
	up such we can use the maya standalone package.
221
	If running within maya or whith maya py, this is true, otherwise we have to
222
	use the MAYA_LOCATION to get this to work.
223
	"""
226
	binBaseName = os.path.split( sys.executable )[1].split( '.' )[0]
227
	if binBaseName[0:4].lower() == 'maya' and binBaseName[0:6].lower() != 'mayapy':
228
		return
232
	locvar = 'MAYA_LOCATION'
233
	if not os.environ.has_key( locvar ):
234
		raise EnvironmentError( locvar + " was not set - it must point to the maya installation directory" )
238
	mayalocation = os.path.realpath(os.environ[locvar])
239
	splitpos = -1
242
	if mayalocation.endswith( "Contents" ):
243
		splitpos = -3
245
	mayabasename = mayalocation.split( os.sep )[ splitpos ]
248
	bits = 32
249
	if mayabasename.endswith( '64' ):
250
		bits = 64
252
	mayabasename = mayabasename.replace( "-x64", "" )	# could be mayaxxxx-x64
253
	mayaversion = mayabasename[4:]				# could be without version, like "maya"
254
	fmayaversion = float(mayaversion)
259
	pymayaversion = sys.version_info[0:2]
260
	if len( mayaversion ):
261
		pyminor = pymayaversion[1]
263
		if float(mayaversion) not in maya_to_py_version_map:
264
			raise EnvironmentError( "Requires Maya 8.5 or higher for python support, found " + mayaversion + " (or maya version is not implemented)" )
266
		pyversion = pymayaversion[0] + (pymayaversion[1]/10.0)
267
		if maya_to_py_version_map[float(mayaversion)] != pyversion:
268
			raise EnvironmentError( "Maya " + mayaversion + " python interpreter requirements not met" )
279
	for path in sys.path[:]:
280
		if os.path.isdir(os.path.join(path, 'maya')) and not path.endswith("site-packages"):
281
			sys.path.remove(path)
287
	if os.name == "nt":
288
		osspecific = os.path.join("Python", "lib")
289
	else:
290
		pyversionstr = str( pymayaversion[0] ) + "." + str( pymayaversion[1] )
291
		osspecific = os.path.join("lib", "python" + pyversionstr, "site-packages")
293
	mayapylibpath = os.path.join( mayalocation, osspecific, "site-packages" )
294
	sys.path.append( mayapylibpath )
299
	mrv._remove_empty_syspath_entries()
301
	try:
302
		import maya
303
	except Exception, e:
304
		print "Paths in sys.path: "
305
		for p in sys.path: print "%r" % p
306
		raise EnvironmentError( "Failed to import maya - check this script or assure LD_LIBRARY path is set accordingly: " + str( e ) )
314
	try:
315
		import maya.standalone
316
		maya.standalone.initialize()
317
	except:
318
		log.debug("Paths in sys.path: ")
319
		for p in sys.path: log.debug("%r" % p)
320
		if 'maya' in locals():
321
			log.info("Imported maya module is located at: %r" % maya.__file__)
322
		log.error("ERROR: Failed initialize maya")
323
		raise
332
	if fmayaversion < 2009:
333
		move_vars_to_environ( )
336
	return
340
def init_path( ):
341
	"""Setup the path type to use slashes internally, no matter which operating 
342
	system we are on"""
343
	import mrv.path
344
	mrv.path.BasePath.set_separator('/')
346
def init_user_prefs( ):
347
	"""intiialize the user preferences according to the set configuration variables"""
348
	try:
349
		init_mel = int(os.environ.get('MRV_STANDALONE_INIT_OPTIONVARS', 0))
350
		run_user_setup = int(os.environ.get('MRV_STANDALONE_RUN_USER_SETUP', 0))
351
		autoload_plugins = int(os.environ.get('MRV_STANDALONE_AUTOLOAD_PLUGINS', 0))
352
	except ValueError, e:
353
		log.warn("Invalid value for MRV configuration variable: %s" % str(e).split(':', 1)[-1])
356
	def source_file_safely(script):
357
		try:
358
			maya.mel.eval('source "%s"' % script)  
359
		except RuntimeError, e:
360
			log.error(str(e) + "- ignored")
364
	if not (init_mel|run_user_setup|autoload_plugins):
365
		return
367
	import maya.cmds as cmds
368
	prefsdir = make_path(cmds.internalVar(userPrefDir=1))
370
	if not prefsdir.isdir():
371
		log.warn("User Preferences directory did not exist: %s" % prefsdir)
372
		return
376
	sources = list()
377
	if init_mel:
378
		sources.append("createPreferencesOptVars.mel")
379
		sources.append("createGlobalOptVars.mel")
380
		sources.append(prefsdir + "/userPrefs.mel")
383
	if autoload_plugins:
384
		sources.append(prefsdir + "/pluginPrefs.mel")
388
	import maya.mel
389
	for scriptpath in sources:
390
		if os.path.isabs(scriptpath) and not os.path.isfile(scriptpath):
391
			log.warn("Couldn't source %s as it did not exist" % scriptpath)
394
		source_file_safely(scriptpath)
397
	if run_user_setup:
399
		source_file_safely("userSetup.mel")
405
def init_singletons( ):
406
	""" Initialize singleton classes and attach them direclty to our module"""
407
	global Scene
408
	global Mel
410
	import scene
411
	Scene = scene.Scene()
413
	import util
414
	Mel = util.Mel()
417
def init_standard_output( ):
418
	"""Assure that logging can print to stdout and stderr which get overwritten
419
	by special maya versions which lack the 'flush' method"""
421
	class PassOnOrDummy(object):
422
		def __init__(self, obj):
423
			self.obj = obj
425
		def does_nothing(self, *args, **kwargs):
426
			return
428
		def __getattr__(self, attr):
429
			try:
430
				return getattr(self.obj, attr)
431
			except AttributeError:
432
				return self.does_nothing
436
	for channame in ('stdout', 'stderr'):
437
		chan = getattr(sys, channame)
438
		if hasattr(chan, 'flush'):
439
			continue
443
		fixedchan = PassOnOrDummy(chan)
444
		setattr(sys, channame, fixedchan)
447
		for l in chain((logging.root, ), logging.root.manager.loggerDict.values()):
448
			if not isinstance(l, logging.Logger):
449
				continue
451
			for handler in l.handlers:
452
				if isinstance(handler, logging.StreamHandler) and handler.stream is chan:
453
					handler.stream = fixedchan
462
if 'init_done' not in locals():
463
	init_done = False
466
if not init_done:
468
	init_system()
469
	init_path()
470
	init_standard_output()
471
	init_modules(__file__, "mrv.maya")
472
	init_singletons()
475
	init_done = True
476
	init_user_prefs()