# batchrif.py
# Instanced by batchrender.BatchRender class. It
# A re-written version of ribops.py
# Started: 22 Jan 2013
# Malcolm Kesson
import re, os, sys, prman, time, inspect, zipfile
class BatchRif():
# Rifs that implement any of these methods will be applied to the zips/ribs
# in the RMS "job" and "frames" directories. Used by self.isGeometryRif().
geoMethods = ['TrimCurve','VArchiveRecord','VPAtmosphere',\
'Blobby','Curves','Cylinder','Disk','GeneralPolygon',\
'GeometricApproximation','Geometry', 'SubdivisionMesh',\
'HierarchicalSubdivisionMesh','PointsGeneralPolygons',\
'Hyperboloid','NuPatch','ObjectBegin','ObjectEnd',\
'ObjectInstance','Paraboloid','Patch','PatchMesh',\
'PointsPolygons','Polygon','Procedural','Torus',\
'ReadArchive','SolidBegin','SolidEnd','Sphere','Volume','Points',]
#-------------------------------------------------
def __init__(self, logpath):
self.logpath = logpath
self.__log('log_rif.txt', '', 'w')
#-------------------------------------------------
# getRifsFromString [public]
#-------------------------------------------------
def getRifsFromString(self, text):
text = text.strip("'")
regx = re.compile(r'[;]')
names = [ ]
parts = regx.split(text)
for part in parts:
# Avoid empty strings
if len(part) > 0:
names.append(part)
if len(names) > 0:
return self.__getRifsFromList(names)
#-------------------------------------------------
# __getRifsFromList [private]
#-------------------------------------------------
def __getRifsFromList(self, rifnames):
out = []
ri = prman.Ri()
out.append(ri)
for name in rifnames:
cls = self.__getClassFromStr(name.strip())
if cls == None:
continue
rifClass = cls[0]
if len(cls) == 1:
rifInst = rifClass(ri)
else:
rifArgs = cls[1]
rifArgs = rifArgs.strip('[]')
regx = re.compile(r'[,]')
parts = regx.split(rifArgs)
args = []
for part in parts:
if len(part) > 0:
if self.__isa_number(part):
args.append(float(part))
else:
args.append(part)
rifInst = rifClass(ri,args)
out.append(rifInst)
return out
#-------------------------------------------------
# __getClassFromStr [private]
#-------------------------------------------------
def __getClassFromStr(self, mcStr):
regx = re.compile(r'[()]')
parts = mcStr.split('.',1)
module = parts[0].strip()
if len(parts) == 1:
parts.append('Rif()')
# Tokenize on '()' to extract any args
tokens = regx.split(parts[1:][0])
tokens = self.__removeEmptyStrs(tokens);
cls = tokens[0].strip()
argStr = ''
if len(tokens) == 2:
argStr = tokens[1]
mcStr = module + '.' + cls
parts = mcStr.split('.')
try:
m = __import__(module)
except:
print'%s' % ('-' * 70)
print('Error: Cannot import module named "%s".' % module)
print('It either does not exist or it has syntax errors.')
print'%s' % ('-' * 70)
return None
for comp in parts[1:]:
m = getattr(m, comp)
out = [m]
argStr = argStr.strip()
if len(argStr):
out.append(argStr)
return out
#-------------------------------------------------
# applyRifsToRibs [public]
#-------------------------------------------------
def applyRifsToRibs(self, rifs, ribs, format):
if len(rifs) == 0 or len(ribs) == 0:
return
# Get the instance of Ri used by any of the Rifs. There can only
# be a single instance of the 'ri' variable and it must be "shared"
# by the rifs so we pick the first Rif and use it to get an
# instance of 'm_ri'.
ri = rifs[0].m_ri
if format == 'ascii':
ri.Option("rib", {"string asciistyle": "indented"})
else:
ri.Option("rib", {"string format": "binary"})
prman.RifInit(rifs)
for rib in ribs:
parent = os.path.dirname(rib)
name = os.path.basename(rib)
if name == 'cutter_history' or name.startswith('cif'):
continue
tmpRib = os.path.join(parent, 'tmp_' + name)
ri.Begin(tmpRib)
prman.ParseFile(rib)
ri.End()
os.remove(rib)
os.rename(tmpRib,rib)
prman.RifInit([]) # will crash without this !!
#msg = 'Filtered %d rib(s) using the following,\n' % len(ribs)
msg = 'Applied:\n'
for rif in rifs:
name = str(rif.__class__)
msg += ' %s\n' % name[8:len(name)-2]
msg += 'to filter:\n'
for rib in ribs:
msg += ' %s\n' % rib
self.__log('log_rif.txt', msg, 'a')
#-------------------------------------------------
# applyRifsToZips [public]
#-------------------------------------------------
def applyRifsToZips(self, rifs, zips, projpath):
for zfile in zips:
self.applyRifsToZip(rifs, zfile, projpath)
#-------------------------------------------------
# applyRifsToZip [public]
#-------------------------------------------------
def applyRifsToZip(self, rifs, zfile, projpath):
# Extract the ribs from the zip file
zip_in = zipfile.ZipFile(zfile)
ribs = []
for rib_path in zip_in.namelist():
# ex rib_path "renderman/sphere3/rib/job/pCubeShape1.job.rib"
# ex projpath "/Users/mkesson/helper_apps/sphere/"
zip_in.extract(rib_path, projpath)
ribs.append(os.path.join(projpath, rib_path))
self.applyRifsToRibs(rifs,ribs,'binary')
# Re-zip the ribs
tmp_zip_fullpath = os.path.join(os.path.dirname(zfile), 'tmp.zip')
if os.path.exists(tmp_zip_fullpath):
os.remove(tmp_zip_fullpath)
tmp_zipfile = zipfile.ZipFile(tmp_zip_fullpath, mode='a')
for rib in ribs:
relative_path = os.path.relpath(rib, projpath)
tmp_zipfile.write(rib, relative_path)
tmp_zipfile.close()
os.remove(zfile)
os.rename(tmp_zip_fullpath,zfile)
for rib in ribs:
os.remove(rib)
# Utility_____________________________________________
def __log(self, logname, logMsg, permission):
f = open(os.path.join(self.logpath,logname), permission)
if permission == 'w':
localtime = time.asctime( time.localtime(time.time()) )
f.write('Time %s.\n' % localtime)
f.write(logMsg)
f.close()
# Utility_____________________________________________
def isGeometryRif(self, rif):
members = inspect.getmembers(rif)
for member in members:
if member[0] in self.geoMethods and str(member[1]).startswith('<bound method'):
return True
return False
# Utility_____________________________________________
def __removeEmptyStrs(self, inlist):
def remove(strn):
return len(strn.strip())
return filter(remove, inlist)
# Utility_____________________________________________
def __isa_number(self, arg):
try:
float(arg)
return True
except ValueError:
return False