text:
import sys, os, inspect, unittest
#from testingutils import setupUnittestModule
from pymel.core import *
import pymel.core.nodetypes as nodetypes
#import pymel
import pymel.internal.factories as _factories
#import maya.cmds as cmds
#
#
#
#
#
#
#def testNodeCmds(verbose=False):
#
#    #emptyFunctions = []
#
#    for funcName in _internal.nodeCommandList:
#        _internal.testNodeCmd( funcName, _internal.cmdlist[funcName], verbose )
#
#    print "done"
#    #print emptyFunctions

def _makeAllAttrTypes(nodeName):
    res = cmds.sphere(n=nodeName)
    cmds.addAttr(ln='short2Attr',at='short2')
    cmds.addAttr(ln='short2a',p='short2Attr',at='short')
    cmds.addAttr(ln='short2b',p='short2Attr',at='short')

    cmds.addAttr(ln='short3Attr',at='short3')
    cmds.addAttr(ln='short3a',p='short3Attr',at='short')
    cmds.addAttr(ln='short3b',p='short3Attr',at='short')
    cmds.addAttr(ln='short3c',p='short3Attr',at='short')

    cmds.addAttr(ln='long2Attr',at='long2')
    cmds.addAttr(ln='long2a',p='long2Attr',at='long')
    cmds.addAttr(ln='long2b',p='long2Attr',at='long')

    cmds.addAttr(ln='long3Attr',at='long3')
    cmds.addAttr(ln='long3a',p='long3Attr',at='long')
    cmds.addAttr(ln='long3b',p='long3Attr',at='long')
    cmds.addAttr(ln='long3c',p='long3Attr',at='long')

    cmds.addAttr(ln='float2Attr',at='float2')
    cmds.addAttr(ln='float2a',p='float2Attr',at="float")
    cmds.addAttr(ln='float2b',p='float2Attr',at="float")

    cmds.addAttr(ln='float3Attr',at='float3')
    cmds.addAttr(ln='float3a',p='float3Attr',at="float")
    cmds.addAttr(ln='float3b',p='float3Attr',at="float")
    cmds.addAttr(ln='float3c',p='float3Attr',at="float")

    cmds.addAttr(ln='double2Attr',at='double2')
    cmds.addAttr(ln='double2a',p='double2Attr',at='double')
    cmds.addAttr(ln='double2b',p='double2Attr',at='double')

    cmds.addAttr(ln='double3Attr',at='double3')
    cmds.addAttr(ln='double3a',p='double3Attr',at='double')
    cmds.addAttr(ln='double3b',p='double3Attr',at='double')
    cmds.addAttr(ln='double3c',p='double3Attr',at='double')

    cmds.addAttr(ln='Int32ArrayAttr',dt='Int32Array')
    cmds.addAttr(ln='doubleArrayAttr',dt='doubleArray')
    cmds.addAttr(ln='pointArrayAttr',dt='pointArray')
    cmds.addAttr(ln='vectorArrayAttr',dt='vectorArray')

    cmds.addAttr(ln='stringArrayAttr',dt='stringArray')
    cmds.addAttr(ln='stringAttr',dt="string")
    cmds.addAttr(ln='matrixAttr',dt="matrix")

    # non numeric
    cmds.addAttr(ln='sphereAttr',dt='sphere')
    cmds.addAttr(ln='coneAttr',dt='cone')
    cmds.addAttr(ln='meshAttr',dt='mesh')
    cmds.addAttr(ln='latticeAttr',dt='lattice')
    cmds.addAttr(ln='spectrumRGBAttr',dt='spectrumRGB')
    cmds.addAttr(ln='reflectanceRGBAttr',dt='reflectanceRGB')
    cmds.addAttr(ln='componentListAttr',dt='componentList')
    cmds.addAttr(ln='attrAliasAttr',dt='attributeAlias')
    cmds.addAttr(ln='curveAttr',dt='nurbsCurve')
    cmds.addAttr(ln='surfaceAttr',dt='nurbsSurface')
    cmds.addAttr(ln='trimFaceAttr',dt='nurbsTrimface')
    cmds.addAttr(ln='polyFaceAttr',dt='polyFaces')

class testCase_mayaSetAttr(unittest.TestCase):
    """
    sanity check: make sure we know how to set and get attributes via maya's
    setAttr.  this serves mostly to document all the inconsistencies in setAttr
    so that we can sort them out in our own wrap.  it will also alert us to
    any changes that Autodesk makes.
    """

    def setUp(self):
        _makeAllAttrTypes('node')

    def test_short2(self):
        # compound
        cmds.setAttr( 'node.short2Attr', 1, 2 )
        assert cmds.getAttr( 'node.short2Attr' )        == [(1, 2)]

    def test_short3(self):
        cmds.setAttr( 'node.short3Attr', 1, 2, 3 )
        assert cmds.getAttr( 'node.short3Attr' )        == [(1, 2,3)]

    def test_long2(self):
        cmds.setAttr( 'node.long2Attr', 1, 2 )
        assert cmds.getAttr( 'node.long2Attr' )         == [(1, 2)]

    def test_long3(self):
        cmds.setAttr( 'node.long3Attr', 1, 2, 3 )
        assert cmds.getAttr( 'node.long3Attr' )         == [(1, 2,3)]

    def test_float2(self):
        cmds.setAttr( 'node.float2Attr', 1, 2 )
        assert cmds.getAttr( 'node.float2Attr' )        == [(1.0, 2.0)]

    def test_float(self):
        cmds.setAttr( 'node.float3Attr', 1, 2, 3 )
        assert cmds.getAttr( 'node.float3Attr' )        == [(1.0, 2.0, 3.0)]

    def test_double2(self):
        cmds.setAttr( 'node.double2Attr', 1, 2 )
        assert cmds.getAttr( 'node.double2Attr' )       == [(1.0, 2.0)]

    def test_double3(self):
        cmds.setAttr( 'node.double3Attr', 1, 2, 3 )
        assert cmds.getAttr( 'node.double3Attr' )       == [(1.0, 2.0, 3.0)]

    def test_int32Array(self):
        # array
        cmds.setAttr( 'node.Int32ArrayAttr', (1, 2, 3, 4), type='Int32Array' )
        assert cmds.getAttr( 'node.Int32ArrayAttr' ) == [1, 2, 3, 4]

    def test_doubleArray(self):
        cmds.setAttr( 'node.doubleArrayAttr', (1, 2, 3, 4), type='doubleArray' )
        assert cmds.getAttr( 'node.doubleArrayAttr' )   == [1.0, 2.0, 3.0, 4.0]

    def test_pointArray(self):
        if versions.current() < versions.v2011:
            # complex array
            cmds.setAttr( 'node.pointArrayAttr', 2, (1,2,3,4), "", (1,2,3,4), type='pointArray' )
            assert cmds.getAttr( 'node.pointArrayAttr' )    == [(1.0, 2.0, 3.0, 4.0), (1.0, 2.0, 3.0, 4.0)]
        else:
            cmds.setAttr( 'node.pointArrayAttr', 2, (1,2,3,4), (1,2,3,4), type='pointArray' )
            assert cmds.getAttr( 'node.pointArrayAttr' )    == [(1.0, 2.0, 3.0, 4.0), (1.0, 2.0, 3.0, 4.0)]

    def test_vectorArray(self):
        if versions.current() < versions.v2011:
            cmds.setAttr( 'node.vectorArrayAttr', 2, (1,2,3), "", (1,2,3), type='vectorArray' )
            assert cmds.getAttr( 'node.vectorArrayAttr' )   == [1.0, 2.0, 3.0, 1.0, 2.0, 3.0]
        else:
            cmds.setAttr( 'node.vectorArrayAttr', 2, (1,2,3), (1,2,3), type='vectorArray' )
            assert cmds.getAttr( 'node.vectorArrayAttr' )   == [(1.0, 2.0, 3.0), (1.0, 2.0, 3.0)]

    def test_stringArray(self):
        # string array
        cmds.setAttr( 'node.stringArrayAttr', 3, 'one', 'two', 'three', type='stringArray' )
        assert cmds.getAttr( 'node.stringArrayAttr' )   == [u'one', u'two', u'three']

    def test_string(self):
        cmds.setAttr( 'node.stringAttr', 'one', type='string' )
        assert cmds.getAttr( 'node.stringAttr' )        == u'one'

    if versions.current() >= versions.v2011:
        def test_matrix(self):
            # matrix
            # Fails in versions < 2011
            cmds.setAttr( 'node.matrixAttr', 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, type='matrix' )
            assert cmds.getAttr( 'node.matrixAttr' )   == [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0]

    def test_sphere(self):
        # non-numeric: can't get
        cmds.setAttr( 'node.sphereAttr', 1.0, type='sphere' )
        #assert cmds.getAttr( 'node.sphereAttr' )        == 1.0

    def test_cone(self):
        cmds.setAttr( 'node.coneAttr', 45, 45, type='cone' )
        #assert cmds.getAttr( 'node.coneAttr' )        == 1.0

    def test_reflectanceRGB(self):
        cmds.setAttr( 'node.reflectanceRGBAttr', 1,1,1, type='reflectanceRGB' )
        #assert cmds.getAttr( 'node.reflectanceRGBAttr' )        == 1.0
        # TODO : finish non-numeric

def test_pymel_setAttr():

    _makeAllAttrTypes('node2')
    for data in [
        ('short2',  (1,2)),
        ('short3',  (1,2,3)),
        ('long2',   (1,2)),
        ('long3',   (1,2,3)),
        ('float2',  (1.0,2.0)),
        ('float3',  (1.0,2.0,3.0)),
        ('double2', (1.0,2.0)),
        ('double3', datatypes.Vector(1.0,2.0,3.0), [1,2,3] ),

        ('Int32Array', [1,2,3,4]),
        ('doubleArray', [1,2,3,4]),

        ('vectorArray', [datatypes.Vector([1,2,3]), datatypes.Vector([1,0,0])],
                        [[1,2,3], [1,0,0]] ),
        ('pointArray', [datatypes.Point([1,2,3]), datatypes.Point([2,4,6])],
                        [[1,2,3,1], [2,4,6,1]] ),

        ('stringArray', ['one', 'two', 'three']),
        ('string', 'one'),
        ('matrix', datatypes.Matrix(),
                        [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0] )]:
        typ = data[0]
        mainVal = data[1]

        for i, val in enumerate(data[1:]):
            def testSetAttr(*args):
                at = 'node2.' + typ + 'Attr'
                setAttr(at, val)
                newval = getAttr(at)
                assert newval == mainVal, "setAttr %s: returned value %r is not equal to input value %r" % (typ, newval, mainVal)

            testSetAttr.__name__ = 'test_setAttr_' + typ + '_' + str(i)
            testSetAttr.description = testSetAttr.__name__
            #print typ
            #testSetAttr()
            yield testSetAttr,

class testCase_nodesAndAttributes(unittest.TestCase):

    def setUp(self):
        self.sphere1, hist = polySphere()
        self.cube1, hist = polyCube()
        self.grp1 = group(self.sphere1, self.cube1)

        #duplicate
        self.grp2 = duplicate(self.grp1)[0]
        self.sphere2, self.cube2 = self.grp2.getChildren()

        #instance
        self.grp3 = instance(self.grp1)[0]
        self.sphere3, self.cube3 = self.grp3.getChildren()

        self.light = spotLight()

        currentTime( 1 )
        setKeyframe( self.light.intensity )
        currentTime( 10 )
        self.light.intensity.set(10)
        setKeyframe( self.light.intensity )
        currentTime( 1 )

        self.anim = self.light.intensity.inputs()[0]

        self.newobjs = []

        cmds.aliasAttr( 'myalias', self.sphere1.name() + '.scaleX' )

    def test_attribute_parent_equality(self):
        self.assertEqual( self.sphere2.t.tx.parent(), self.sphere2.t )

    def test_attribute_duplicate_inequality(self):
        self.assert_( self.sphere1.t != self.sphere2.t )

    def test_attribute_instance_equality(self):
        self.assertEqual( self.sphere1.t, self.sphere3.t )

    def test_attribute_cascading(self):
        self.sphere1.primaryVisibility.set(1)
        shape = self.sphere1.getShape()
        self.assertEqual( self.sphere1.primaryVisibility, shape.primaryVisibility )

    def test_attribute_aliases(self):
        self.assert_( isinstance(PyNode(self.sphere1.name() + '.myalias'), Attribute ) )
        self.assert_( isinstance(self.sphere1.attr('myalias'), Attribute) )
        res1 = self.sphere1.listAttr(alias=1)
        res2 = self.sphere1.listAliases()
        self.assertEqual( res1[0], res2[0][1] )

    def test_pmcmds_objectErrors(self):
        self.assertRaises( MayaAttributeError, setAttr, 'foo.bar', 0 )
        self.assertRaises( MayaAttributeError, getAttr, 'foo.bar' )
        self.assertRaises( MayaNodeError, listConnections, 'foobar' )

    def test05_dagNode_addParent(self):
        sphere = polySphere()[0]
        cube = polyCube()[0]
        torus = polyTorus()[0]
        sphere | cube | torus
        print torus.fullPath()

    #def test05_dagNode_getParent(self):
    def test06_instances(self):
        self.assert_( self.sphere1.isInstanced() )
        self.assert_( self.sphere1.isInstanceOf( self.sphere3 ) )

    def test_parentsAndChildren(self):
        shape = self.sphere1.getShape()
        self.assertEqual( shape, self.sphere1.childAtIndex(0) )
        shape.hasParent( self.sphere1 )
        self.assert_( shape.hasParent(self.sphere1) )
        self.assert_( self.sphere1.hasChild(shape) )

        self.sphere2 | self.grp1
        # Should now have grp2 | sphere2 | grp1 | cube1
        self.assertEqual(self.cube1.getParent(0), self.cube1)
        self.assertEqual(self.cube1.getParent(generations=1), self.grp1)
        self.assertEqual(self.cube1.getParent(2), self.sphere2)
        self.assertEqual(self.cube1.getParent(generations=3), self.grp2)
        self.assertEqual(self.cube1.getParent(-1), self.grp2)
        self.assertEqual(self.cube1.getParent(generations=-2), self.sphere2)
        self.assertEqual(self.cube1.getParent(-3), self.grp1)
        self.assertEqual(self.cube1.getParent(generations=-4), self.cube1)
        self.assertEqual(self.cube1.getParent(-5), None)
        self.assertEqual(self.cube1.getParent(generations=4), None)
        self.assertEqual(self.cube1.getParent(-63), None)
        self.assertEqual(self.cube1.getParent(generations=32), None)

    def test07_units(self):
        startLinear = currentUnit( q=1, linear=1)
        startAngular = currentUnit( q=1, angle=1)
        startTime = currentUnit( q=1, time=1)
        #cam = PyNode('persp')

        # change to units that differ from api internal units

        currentUnit(linear='meter')
        currentUnit(angle='deg')
        currentUnit(time='120fps')

        testPairs = [ ('persp.translate', 'getTranslation', 'setTranslation', datatypes.Vector([3.0,2.0,1.0]) ),  # Distance Vector
                      ('persp.shutterAngle' , 'getShutterAngle', 'setShutterAngle', 144.0 ),  # Angle
                      ('persp.verticalFilmAperture' , 'getVerticalFilmAperture', 'setVerticalFilmAperture', 2.0 ),  # Unitless
                      ('persp.focusDistance', 'getFocusDistance', 'setFocusDistance', 5.0 ),  # Distance
                      ('%s.penumbraAngle' % self.light, 'getPenumbra', 'setPenumbra', 5.0 ),  # Angle with renamed api method ( getPenumbraAngle --> getPenumbra )
                     ]
        print
        for attrName, getMethodName, setMethodName, realValue in testPairs:
            at = PyNode(attrName)
            node = at.node()
            getter = getattr( node, getMethodName )
            setter = getattr( node, setMethodName )

            print repr(at)
            print "Real Value:", repr(realValue)
            # set attribute using "safe" method
            at.set( realValue )
            # get attribute using wrapped api method
            gotValue = getter()
            print "Got Value:", repr(gotValue)
            # compare
            self.assertEqual( realValue, gotValue )

            # set using wrapped api method
            setter( realValue )
            # get attribute using "safe" method
            gotValue = at.get()
            # compare
            self.assertEqual( realValue, gotValue )

        self.assert_( self.anim.keyTimeValue[1].keyTime.get() == self.anim.getTime(1) )
        self.anim.setTime(1, 5.0)
        self.assert_( self.anim.keyTimeValue[1].keyTime.get() == self.anim.getTime(1) )
        # reset units
        currentUnit(linear=startLinear)
        currentUnit(angle=startAngular)
        currentUnit(time=startTime)

#    def test_components(self):
#        import pymel.examples.setVertexColor
#        pymel.examples.setVertexColor.doIt( self.sphere1 )
#
#    def test_examples(self):
#        import pymel.examples.example1
#        import pymel.examples.example2

    def test_classCreation(self):
        self.newobjs.append( Joint() )
        self.newobjs.append( Transform() )

    def test_transform_translation(self):
        SCENE.persp.setTranslation( [10,20,30], 'world')

        self.assert_( SCENE.persp.getTranslation( 'world' ) == datatypes.Vector([10.0, 20.0, 30.0]) )
        SCENE.persp.setTranslation( [1,2,3], 'world', relative=1)

        self.assert_( SCENE.persp.getTranslation( 'world' ) == datatypes.Vector([11.0, 22.0, 33.0]) )

        undo()
        self.assert_( SCENE.persp.getTranslation( 'world' ) == datatypes.Vector([10.0, 20.0, 30.0]) )

    def test_transform_scale(self):

        SCENE.persp.setScale( [10,20,30] )

        self.assert_( SCENE.persp.getScale() == [10.0, 20.0, 30.0] )
        SCENE.persp.setScale( [1,2,3], relative=1)

        self.assert_( SCENE.persp.getScale() == [10.0, 40.0, 90.0] )

        undo()
        self.assert_( SCENE.persp.getScale() == [10.0, 20.0, 30.0] )

    def test_transform_rotation(self):
        SCENE.persp.setRotation( [10,20,0], 'world')
        print repr( SCENE.persp.getRotation( 'world' ) )
        self.assert_( SCENE.persp.getRotation( 'world' ).isEquivalent( datatypes.EulerRotation([10.0, 20.0, 0.0])) )
        SCENE.persp.setRotation( [0,90,0], 'world', relative=1)

        self.assert_( SCENE.persp.getRotation( 'world' ).isEquivalent( datatypes.EulerRotation([10.0, 110.0, 0.0])) )

        undo()
        self.assert_( SCENE.persp.getRotation( 'world' ).isEquivalent( datatypes.EulerRotation([10.0, 20.0, 00.0])) )

    def test_immutability(self):

        c1 = polyCube()[0]
        c2 = polyCube()[0]

        nodeHash1 = c1.__hash__()
        nodeHash2 = c2.__hash__()

        attrHash1 = c1.translate.__hash__()
        attrHash2 = c2.translate.__hash__()

        self.assert_ ( nodeHash1 != nodeHash2 )
        self.assert_ ( attrHash1 != attrHash2 )

        c1.rename( 'funfun' )
        c2.rename( 'yumyum' )

        self.assert_( nodeHash1 == c1.__hash__() )
        self.assert_( nodeHash2 == c2.__hash__() )
        self.assert_( attrHash1 == c1.translate.__hash__() )
        self.assert_( attrHash2 == c2.translate.__hash__() )

    def test_pynode_instantiation(self):
        plug = SCENE.persp.__apimfn__().findPlug('translateX')
        obj = SCENE.persp.__apimobject__()
        dag = SCENE.persp.__apimdagpath__()
        PyNode(obj).name()
        PyNode(plug).name()
        PyNode(dag).name()

    def tearDown(self):
        newFile(f=1)

class testCase_apiUndo(unittest.TestCase):

    def setUp(self):

        # reset all undo queues
        cmds.undoInfo(state=0)
        setAttr( 'persp.focalLength', 35 )
        setAttr( 'top.focalLength', 35 )
        factories.apiUndo.flushUndo()
        cmds.undoInfo(state=1)

    def test_undo(self):
        self.assert_( len(factories.apiUndo.undo_queue) == 0 )

        SCENE.top.setFocalLength(20)
        self.assert_( len(factories.apiUndo.undo_queue) == 1 )

        undoInfo(stateWithoutFlush=0)#--------------------------------

        SCENE.persp.setFocalLength(20)
        self.assert_( len(factories.apiUndo.undo_queue) == 1 )

        undoInfo(stateWithoutFlush=1)#--------------------------------

        undo() # undo top focal length back to 35

        self.assert_( SCENE.top.getFocalLength() == 35.0 )
        self.assert_( SCENE.persp.getFocalLength() == 20.0 )

        redo()

        self.assert_( SCENE.top.getFocalLength() == 20.0 )
        self.assert_( SCENE.persp.getFocalLength() == 20.0 )
        self.assert_( len(factories.apiUndo.undo_queue) == 1 )

        # clear maya's undo queue
        # we override undoInfo in system to flush the cache
        undoInfo( state=0)
        undoInfo( state=1)

        self.assert_( len(factories.apiUndo.undo_queue) == 0 )

        SCENE.top.setFocalLength(200)
        undo()

        self.assert_( SCENE.persp.getFocalLength() == 20.0 )
        self.assert_( SCENE.top.getFocalLength() == 20.0 )

        self.assert_( len(factories.apiUndo.undo_queue) == 0 )

#    def tearDown(self):
#
#        # reset all undo queues
#        cmds.undoInfo(state=0)
#        setAttr( 'persp.focalLength', 35 )
#        setAttr( 'top.focalLength', 35 )
#        factories.apiUndo.flushUndo()
#        cmds.undoInfo(state=1)

    def tearDown(self):
        # cleaning
        newFile(f=1)

class testCase_listHistory(unittest.TestCase):

    def setUp(self):
        self.sphere1, self.sphere1Maker = polySphere()
        self.sphere1Shape = self.sphere1.getShape()
        self.cube1 = polyCube()[0]
        self.cube1Shape = self.cube1.getShape()

        # Delete cube's construction history
        delete(self.cube1, ch=1)

        # Connect sphere up to cube
        self.sphere1Shape.outMesh >> self.cube1Shape.inMesh

        self.justSphereShape = set([self.sphere1Shape])
        self.justPolySphere = set([self.sphere1Maker])
        self.justCubeShape = set([self.cube1Shape])
        self.polySphereAndShape = self.justSphereShape | self.justPolySphere
        self.polySphereAndShapeAndCubeShape = self.polySphereAndShape | self.justCubeShape
        self.shapes = self.justSphereShape | self.justCubeShape

    def tearDown(self):
        # cleaning
        delete(self.sphere1)
        delete(self.cube1)

    def test_listHistory(self):
        hist = set(self.sphere1.listHistory())
        self.assertEqual(self.polySphereAndShape, hist)

        hist = set(self.cube1.listHistory())
        self.assertEqual(self.polySphereAndShapeAndCubeShape, hist)

    def test_listHistoryType(self):
        hist = set(self.sphere1.listHistory(type='dagNode'))
        self.assertEqual(self.justSphereShape, hist)

        hist = set(self.sphere1.listHistory(type='mesh'))
        self.assertEqual(self.justSphereShape, hist)

        hist = set(self.cube1.listHistory(type='dagNode'))
        self.assertEqual(self.shapes, hist)

        hist = set(self.cube1.listHistory(type='mesh'))
        self.assertEqual(self.shapes, hist)

    def test_listHistoryExactType(self):
        hist = set(self.sphere1.listHistory(exactType='dagNode'))
        self.assertEqual(set(), hist)

        hist = set(self.sphere1.listHistory(exactType='mesh'))
        self.assertEqual(self.justSphereShape, hist)

        hist = set(self.cube1.listHistory(exactType='dagNode'))
        self.assertEqual(set(), hist)

        hist = set(self.cube1.listHistory(exactType='mesh'))
        self.assertEqual(self.shapes, hist)

    def test_listFuture(self):
        fut = set(self.sphere1Maker.listFuture())
        self.assertEqual(self.polySphereAndShapeAndCubeShape, fut)

    def test_listFutureType(self):
        fut = set(self.sphere1Maker.listFuture(type='dagNode'))
        self.assertEqual(self.shapes, fut)

        fut = set(self.sphere1Maker.listFuture(type='mesh'))
        self.assertEqual(self.shapes, fut)

    def test_listFutureExactType(self):
        fut = set(self.sphere1Maker.listFuture(exactType='dagNode'))
        self.assertEqual(set(), fut)

        fut = set(self.sphere1Maker.listFuture(exactType='mesh'))
        self.assertEqual(self.shapes, fut)

#    def test_transform(self):
#        s, h = polySphere()
#        g = group(s)
#        s.setTranslation( [0,10,20] )
#        s.getTranslation(objectSpace=1)
#        # Result: [0.0, 10.0, 20.0] #
#        s.getTranslation('object')
#        # Result: [0.0, 10.0, 20.0] #
#        s.getTranslation(worldSpace=1)
#        # Result: [10.0, 10.0, 20.0] #
#        s.getTranslation('world')
#        # Result: [10.0, 10.0, 20.0] #

class testCase_duplicateShape(unittest.TestCase):
    def setUp(self):
        cmds.file(new=1, f=1)
        self.poly = polyCube(name='singleShapePoly')[0]
        self.curve = circle(name='singleShapeCurve')[0]
        tempShapeTransform = polyCone()[0]
        self.subd = polyToSubdiv(tempShapeTransform,
                                 constructionHistory=False,
                                 name='singleShapeSubd')[0]
        delete(tempShapeTransform)
        #self.noShape = createNode('transform', name='noShapeTransform')

        #one transform, multiple shapes
        self.multiShape = polyCube(name='multiShape')[0]
        self.multiShape.getShape().rename('multiShapePolyShape')
        tempShapeTransform = polyToSubdiv(self.multiShape,
                                          constructionHistory=False,
                                          name='multiShapeSubd')[0]
        parent(tempShapeTransform.getShape(), self.multiShape, shape=True,
               addObject=True, relative=True)
        delete(tempShapeTransform)
        tempShapeTransform = circle(name='multiShapeCurve')[0]
        parent(tempShapeTransform.getShape(), self.multiShape, shape=True,
               addObject=True, relative=True)
        delete(tempShapeTransform)

    def tearDown(self):
        for node in (self.multiShape, self.poly, self.curve, self.subd):
            delete(node)

    def test_singleShapes(self):
        for shapeTransform in (self.poly, self.curve, self.subd):
            self.assertEqual(len(shapeTransform.getChildren(shapes=1)), 1)
            self.assertRaises(TypeError, duplicate, shapeTransform, addShape=True)
            self.assertEqual(len(shapeTransform.getChildren(shapes=1)), 1)
            origShape = shapeTransform.getShape()
            shapeDup = duplicate(origShape, addShape=True)
            self.assertEqual(len(shapeTransform.getChildren(shapes=1)), 2)
            self.assertEqual(len(shapeDup), 1)
            shapeDup = shapeDup[0]
            self.assertDupeShape(origShape, shapeDup)

    def test_multiShape(self):
        origShapes = self.multiShape.getChildren(shapes=1)
        oldNumChildren = len(origShapes)
        self.assertRaises(TypeError, duplicate, self.multiShape, addShape=True)
        self.assertEqual(len(self.multiShape.getChildren(shapes=1)),
                             oldNumChildren)
        for origShape in origShapes:
            shapeDup = duplicate(origShape, addShape=True)
            self.assertEqual(len(self.multiShape.getChildren(shapes=1)),
                             oldNumChildren + 1)
            oldNumChildren += 1
            self.assertEqual(len(shapeDup), 1)
            shapeDup = shapeDup[0]
            self.assertDupeShape(origShape, shapeDup)

    def assertDupeShape(self, origShape, shapeDup):
            self.assertTrue(shapeDup.__class__ == origShape.__class__)

            # As of Maya 2009, shapeCompare doesn't handle subdivs, and always
            #    returns 1 for curves
            if not isinstance(origShape, (Subdiv, NurbsCurve)):
                if shapeCompare(origShape, shapeDup) != 0:
                    self.fail("shapes do not compare equal: %r, %r)" %
                              (origShape, shapeDup))
            self.assertFalse(origShape.isInstanceOf(shapeDup))

class test_PyNodeWraps(unittest.TestCase):
    def setUp(self):
        cmds.file(new=1, f=1)

    def assertPyNode(self, obj, nodeType=PyNode):
        self.assert_(isinstance(obj, nodeType),
                     '%r was not a %s object' % (obj, nodeType.__name__))

    def assertPyNodes(self, objs, nodeType=PyNode):
        for obj in objs:
            self.assertPyNode(obj, nodeType)

    def test_addAttr_QParent(self):
        cmds.polyCube()
        cmds.addAttr( longName='sampson', numberOfChildren=5, attributeType='compound' )
        cmds.addAttr( longName='homeboy', attributeType='matrix', parent='sampson' )
        cmds.addAttr( longName='midge', attributeType='message', parent='sampson' )
        cmds.addAttr( longName='damien', attributeType='double', parent='sampson' )
        cmds.addAttr( longName='elizabeth', attributeType='double', parent='sampson' )
        cmds.addAttr( longName='sweetpea', attributeType='double', parent='sampson' )
        node = cmds.ls(sl=1)[0]
        self.assertPyNode(addAttr(node + '.sweetpea', q=1, parent=1), Attribute)

    def test_skinCluster_QGeometry(self):
        cube = cmds.polyCube()[0]
        j1 = cmds.joint(p=(0,0,-1))
        cmds.joint(p=(0,0,1))
        skin = skinCluster(cube, j1)[0]
        self.assertPyNodes(skin.getGeometry(), DependNode)

    def test_addDynamic(self):
        # Create an emitter
        cmds.emitter( pos=(0, 0, 0), type='omni', r=100, sro=0, nuv=0, cye='none', cyi=1, spd=1, srn=0, nsp=1, tsp=0, mxd=0, mnd=0, dx=1, dy=0, dz=0, sp=0 )
        # Result: emitter1 #

        # Get the emitter to emit particles
        cmds.particle()
        # Result: particle2
        cmds.connectDynamic( 'particle1', em='emitter1' )

        # Create a particle to use as the source of the emitter
        cmds.particle( p=((6.0, 0, 7.0), (6.0, 0, 2.0)), c=1 )
        # Result: particle2

        # Use particle2 as a source of the emitter
        self.assertPyNodes(addDynamic( 'emitter1', 'particle2' ), PyNode)

    def test_addPP(self):
        cmds.emitter( n='myEmitter1' )
        cmds.particle( n='myParticle1' )
        cmds.connectDynamic( 'myParticle1', em='myEmitter1' )
        cmds.select( 'myParticle1' )
        cmds.emitter( n='myEmitter2' )
        cmds.particle( n='myParticle2' )
        cmds.connectDynamic( 'myParticle2', em='myEmitter2' )
        self.assertPyNodes(addPP( 'myEmitter2', atr='rate' ))

    def test_animLayer(self):
        self.assertEqual(animLayer(q=1, root=1), None)
        cmds.animLayer("layer1")
        rootLayer = animLayer(q=1, root=1)
        self.assertPyNode(rootLayer)
        self.assertEqual(animLayer(rootLayer, q=1, parent=1), None)
        self.assertPyNode(animLayer("layer1", q=1, parent=1))
        self.assertEqual(animLayer("layer1", q=1, children=1), [])
        self.assertPyNodes(animLayer(rootLayer, q=1, children=1))
        self.assertEqual(animLayer("layer1", q=1, attribute=1), [])
        self.assertEqual(animLayer("layer1", q=1,  blendNodes=1), [])
        cmds.animLayer("layer1", e=1, attribute=('persp.tx', 'persp.ry'))
        self.assertPyNodes(animLayer("layer1", q=1, attribute=1), Attribute)
        cmds.select('persp')
        self.assertPyNodes(animLayer(q=1, bestAnimLayer=1))
        self.assertEqual(animLayer("layer1", q=1,  animCurves=1), [])
        cmds.setKeyframe('persp', animLayer='layer1')
        self.assertPyNodes(animLayer("layer1", q=1,  animCurves=1))
        self.assertEqual(animLayer('layer1', q=1, bac=1), [])
        cmds.setKeyframe('persp', animLayer='BaseAnimation')
        self.assertPyNodes(animLayer('layer1', q=1, bac=1))
        self.assertPyNodes(animLayer("layer1", q=1,  blendNodes=1))
        self.assertEqual(animLayer("persp.tz", q=1,  bestLayer=1), None)
        self.assertPyNode(animLayer("persp.tx", q=1,  bestLayer=1))
        cmds.select('side')
        self.assertEqual(animLayer(q=1,  affectedLayers=1), [])
        cmds.select('persp')
        self.assertPyNodes(animLayer(q=1,  affectedLayers=1))

    def test_annotate(self):
        cmds.sphere( name='mySphere' )
        self.assertPyNode(annotate( 'mySphere', tx='my annotation text', p=(5, 6, 5) ))

    def test_arclen(self):
        circle(name='curve1')
        self.assertPyNode(arclen('curve1', ch=True))
        self.assertPyNode(arclen('curve1'), float)

    def test_arcLengthDimension(self):
        cmds.curve( d=3, p=((-9.3, 0, 3.2), (-4.2, 0, 5.0), (6.0, 0, 8.6), (2.1, 0, -1.9)), k=(0, 0, 0, 1, 2, 2));
        self.assertPyNode(arcLengthDimension( 'curveShape1.u[0.5]' ))

    def test_arrayMapper(self):
        particle( p=[(0, 0, 0), (3, 5, 6), (5, 6, 7), (9, 9, 9)] )
        self.assertPyNode(arrayMapper( target='particle1', destAttr='rampPosition', inputV='ageNormalized', type='ramp' ))

    if not cmds.about(batch=1):

        def test_art3dPaintCtx(self):
            polyCube()
            polyCube()
            select('pCube1', 'pCube2')
            from maya.mel import eval as mel
            mel("Art3dPaintTool")
            mel("art3dPaintAssignFileTextures color")
            self.assertPyNodes(art3dPaintCtx('art3dPaintContext', q=1, shn=1))
            self.assertPyNodes(art3dPaintCtx('art3dPaintContext', q=1, hnm=1))

        def test_artAttrCtx(self):
            polyCube()
            polyCube()
            select('pCube1', 'pCube2')
            if not cmds.artAttrCtx('artAttrCtx1', exists=1):
                cmds.artAttrCtx('artAttrCtx1')
            cmds.setToolTo('artAttrCtx1')
            self.assertPyNodes(artAttrCtx('artAttrCtx1', q=1, paintNodeArray=1))

for cmdName in ('''aimConstraint geometryConstraint normalConstraint
                   orientConstraint parentConstraint pointConstraint
                   pointOnPolyConstraint poleVectorConstraint
                   scaleConstraint tangentConstraint''').split():
    melCmd = getattr(cmds, cmdName, None)
    if not melCmd: continue
    pyCmd = globals()[cmdName]
    def constraintTest(self):
        cmds.polyCube(name='cube1')
        cmds.circle(name='circle1')
        constr = melCmd( 'circle1', 'cube1')[0]
        self.assertPyNodes(pyCmd(constr, q=1, targetList=1))
        self.assertPyNodes(pyCmd(constr, q=1, weightAliasList=1), Attribute)
        if 'worldUpObject' in _factories.cmdlist[cmdName]['flags']:
            self.assertEqual(pyCmd(constr, q=1, worldUpObject=1), None)
            cmds.polySphere(name='sphere1')
            melCmd(constr, e=1, worldUpType='object', worldUpObject='sphere1')
            self.assertPyNode(pyCmd(constr, q=1, worldUpObject=1))
    testName = "test_" + cmdName
    constraintTest.__name__ = testName
    setattr(test_PyNodeWraps, testName, constraintTest)

    # Delete the function from the module level after we're done, so
    # nosetests won't find the "original" non-method function, and
    # try to run it as a test!
    del globals()['constraintTest']

class test_commands(unittest.TestCase):
    def setUp(self):
        cmds.file(new=1, f=1)
        self.dependNode = cmds.createNode('displayLayer')
        self.group = cmds.group('persp')

    def test_duplicate(self):
        # make sure that we get proper dag nodes, even when the result will contain non-unique names
        self.assert_( duplicate(self.group) )

        # ensure it works with depend nodes too
        self.assert_( duplicate(self.dependNode) )

class test_plugins(unittest.TestCase):
    def test01_load(self):
        loadPlugin('Fur')
        self.assert_( 'FurGlobals' not in pymel.core.nodetypes.__dict__ )
        # lazer loader exists
        self.assert_( 'FurGlobals' in pymel.core.nodetypes.__class__.__dict__ )
        # after accessing, the lazy loader should generate the class
        pymel.core.nodetypes.FurGlobals
        self.assert_( 'FurGlobals' in pymel.core.nodetypes.__dict__ )

    def test1_unload(self):
        unloadPlugin('Fur')
        self.assert_( 'FurGlobals' not in pymel.core.nodetypes.__dict__ )
        # after accessing, the lazy loader should generate the class
        self.assertRaises(AttributeError, getattr, pymel.core.nodetypes, 'FurGlobals')
        self.assert_( 'FurGlobals' not in pymel.core.nodetypes.__dict__ )
        self.assert_( 'FurGlobals' not in pymel.core.nodetypes.__class__.__dict__ )

#suite = unittest.TestLoader().loadTestsFromTestCase(testCase_nodesAndAttributes)
#suite.addTest(unittest.TestLoader().loadTestsFromTestCase(testCase_listHistory))
#unittest.TextTestRunner(verbosity=2).run(suite)
#setupUnittestModule(__name__)


text:
@charset "utf-8";
/* Simple fluid media
   Note: Fluid media requires that you remove the media's height and width attributes from the HTML
   http://www.alistapart.com/articles/fluid-images/
*/
img, object, embed, video {
	max-width: 100%;
}
/* IE 6 does not support max-width so default to width 100% */
.ie6 img {
	width:100%;
}

/*
	Dreamweaver Fluid Grid Properties
	----------------------------------
	dw-num-cols-mobile:		5;
	dw-num-cols-tablet:		8;
	dw-num-cols-desktop:	10;
	dw-gutter-percentage:	25;

	Inspiration from "Responsive Web Design" by Ethan Marcotte
	http://www.alistapart.com/articles/responsive-web-design

	and Golden Grid System by Joni Korpi
	http://goldengridsystem.com/
*/

/* Mobile Layout: 480px and below. */

.gridContainer {
	margin-left: auto;
	margin-right: auto;
	width: 96%;
	padding-left: 2%;
	padding-right: 2%;

}

/* Tablet Layout: 481px to 768px. Inherits styles from: Mobile Layout. */

@media only screen and (min-width: 481px) {
.gridContainer {
	width: 97.5%;
	padding-left: 1.25%;
	padding-right: 1.25%;
}
}

/* Desktop Layout: 769px to a max of 1232px.  Inherits styles from: Mobile Layout and Tablet Layout. */

@media only screen and (min-width: 769px) {
.gridContainer {
	width: 98%;
	max-width: 1232px;
	padding-left: 1%;
	padding-right: 1%;
	margin: auto;
}

.slider {
	margin-left: auto;
	margin-right: auto;
	width: 100%;
	padding:0;

}
.footer {
	background-color:#000;
}
.gridContainer{
	min-width:100%;
	padding-left:0;
	padding-right:0;
}

redpajama_set_name: RedPajamaGithub


text:
<?php
/*******************************************************************************
 * purpose: contains general functions to be used by all programs
 ******************************************************************************/

//<-- begin class -->
class General {
	protected $className = __CLASS__;	// class name
	protected $verbose;
	protected $fileIgnoreList = array('.', '..', '.DS_Store','.svn','.git*');
	protected $varIgnoreList = array('HTTP_POST_VARS', 'HTTP_GET_VARS',
		'HTTP_COOKIE_VARS', 'HTTP_SERVER_VARS', 'HTTP_ENV_VARS',
		'HTTP_SESSION_VARS', '_ENV', 'PHPSESSID','SESS_DBUSER',
		'SESS_DBPASS','HTTP_COOKIE', 'GLOBALS', '_ENV', 'HTTP_ENV_VARS', 'argv',
		'argc', '_POST', 'HTTP_POST_VARS', '_GET', 'HTTP_GET_VARS', '_COOKIE',
		'HTTP_COOKIE_VARS', '_SERVER', 'HTTP_SERVER_VARS', '_FILES',
		'HTTP_POST_FILES', '_REQUEST', 'ignoreList',
	);

	/***************************************************************************
	 * The class constructor
	 *
	 * @param 	boolean $verbose	enable verbose comments
	 **************************************************************************/
	public function __construct($verbose = FALSE) {
		$this->verbose = $verbose;

		if ($this->verbose) {
			fwrite(STDOUT, "$this->className class constructor set.\n");
		} //<-- end if -->
	} //<-- end function -->

	/***************************************************************************
	 * Returns the extension of a file
	 *
	 * @param 	string 	$file 		a filename or the path to a file
	 * @return 	string	$ext		the file extension
	 * @throws 	Exception if $file is empty
	 **************************************************************************/
	public function getExtension($file) {
		if (empty($file)) {
			throw new Exception('Empty file passed from '.$this->className.'->'.
				__FUNCTION__.'() line '.__LINE__
			);
		} else {
			try {
				$ext = pathinfo($file, PATHINFO_EXTENSION);
				return $ext;
			} catch (Exception $e) {
				throw new Exception($e->getMessage().' from '.$this->className
					.'->'.__FUNCTION__.'() line '.__LINE__
				);
			} //<-- end try -->
		} //<-- end if -->
	} //<-- end function -->

	/***************************************************************************
	 * Returns the ordinal suffix of a num, e.g., 1st, 2nd, 3rd.
	 *
	 * @param 	integer	$num a number
	 * @return 	string	$ext a number with the ordinal suffix
	 **************************************************************************/
	public function addOrdinal($num) {
		try {
			if (!in_array(($num % 100), array(11, 12, 13))){
				switch ($num % 10) {
					// Handle 1st, 2nd, 3rd
					case 1: return $num.'st';
					case 2: return $num.'nd';
					case 3: return $num.'rd';
				}
			}

			return $num.'th';

		} catch (Exception $e) {
			throw new Exception($e->getMessage().' from '.$this->className
				.'->'.__FUNCTION__.'() line '.__LINE__
			);
		} //<-- end try -->
	} //<-- end function -->

	/***************************************************************************
	 * A date function supporting the microseconds.
	 *
	 * @param 	string	$format 		time format
	 * @param 	integer	$uTimeStamp 	time (defaults to the value of time())
	 * @return 	string	$newTimestamp 	time with microseconds
	 **************************************************************************/
	public function udate($format, $uTimeStamp = NULL) {
		try {
			if (is_null($uTimeStamp)) {
				$uTimeStamp = microtime(true);
			}

			$timeStamp = floor($uTimeStamp);
			$milliSeconds = round(($uTimeStamp - $timeStamp) * 1000000);
			$newTimestamp = date(preg_replace('`(?<!\\\\)u`', $milliSeconds,
				$format), $timeStamp
			);

			return $newTimestamp;
		} catch (Exception $e) {
			throw new Exception($e->getMessage().' from '.$this->className
				.'->'.__FUNCTION__.'() line '.__LINE__
			);
		} //<-- end try -->
	} //<-- end function -->

	/***************************************************************************
	 * Recursively searches an array for the nth occurance of a given value
	 * type and returns the corresponding key if successful. If passed a
	 * multi-dimensional array, it will returns an array of keys.
	 *
	 * @param 	array 	$haystack 	the array to search
	 * @param 	string 	$needle 	the type of element to find (i.e. 'numeric'
	 *								or 'string')
	 * @param 	int 	$n 			the nth element to find
	 * @return 	mixed	the key (or array of keys) of the found element(s)
	 * @throws 	Exception if it can't find enough elements
	 * @throws 	Exception if $needle is invalid
	 **************************************************************************/
	public function arraySearchType($needle, $haystack, $n = 1) {
		try {
			$i = 0; // needle element counter

			foreach ($haystack as $key => $value) {
				// check to make sure I haven't found too many elements
				if ($i < $n) {
					// It's not an array, so look for needle elements
					if (!is_array($value)) {
						switch ($needle){
							case 'numeric':
								if (is_numeric($value)) {
									$needleKeys[] = $key;
									$i++;
								} //<-- end if -->

								break;

							case 'string':
								if (!is_numeric($value)) {
									$needleKeys[] = $key;
									$i++;
								} //<-- end if -->

								break;

							default:
								throw new Exception('Wrong search type '.
									'entered. Please type \'numeric\' or '.
									'\'string\'.'
								);
						} //<-- end switch -->
					} else { // it IS an array, so recurse
						$needleKeys[] = self::arraySearchType(
							$needle, $value, $n
						);
					} //<-- end if !is_array -->
				} //<-- end if $i < $n -->
			} //<-- end foreach -->

			// check to see if I recursed
			if (count($needleKeys) > 1
				&& count(array_unique($needleKeys)) == 1)
			{
				// I recursed so return entire array of last keys
				return $needleKeys;
			} else { // I didn't recurse
				// check to make sure I found enough elements
				if (count($needleKeys) >= $n) {
					// I only want the last key found
					$lastKey = array_pop($needleKeys);
					return $lastKey;
				} else {
					throw new Exception('Array does not contain '.$n.
						' '.$needle.' elements'
					);
				} //<-- end if -->
			} //<-- end if -->

		} catch (Exception $e) {
			throw new Exception($e->getMessage().' from '.$this->className.'->'.
				__FUNCTION__.'() line '.__LINE__
			);
		} //<-- end try -->
	} //<-- end function -->

	/***************************************************************************
	 * Writes data to a file
	 *
	 * @param 	string 	$content 	the data to write to the file
	 * @param 	string 	$file 		the path to an empty or non existing file
	 * @return 	boolean	TRUE
	 * @throws 	Exception if $content is empty
	 * @throws 	Exception if $file exists as a non-empty file
	 **************************************************************************/
	public function write2File($content, $file) {
		if (empty($content)) { // check to make sure $content isn't empty
			throw new Exception('Empty content passed from '.$this->className.
				'->'.__FUNCTION__.'() line '.__LINE__
			);
		} elseif (file_exists($file) && filesize($file) != 0) {
			throw new Exception('File '.$file.' already exists from '.
				$this->className.'->'.__FUNCTION__.'() line '.__LINE__
			);
		} else {
			try {
				$handle = fopen($file, 'w');
				$bytes = fwrite($handle, $content);
				fclose($handle);

				if ($this->verbose) {
					fwrite(STDOUT, "Wrote $bytes bytes to $file!\n");
				} //<-- end if -->

				return TRUE;
			} catch (Exception $e) {
				throw new Exception($e->getMessage().' from '.$this->className
					.'->'.__FUNCTION__.'() line '.__LINE__
				);
			} //<-- end try -->
		} //<-- end if -->
	} //<-- end function -->

	/***************************************************************************
	 * Writes data to a file (overwrites file if it exists)
	 *
	 * @param 	string 	$content 	the data to write to the file
	 * @param 	string 	$file 		the path to a file
	 * @return 	boolean	TRUE
	 **************************************************************************/
	public function overwriteFile($content, $file) {
		try {
			if (!file_exists($file)) {
				self::write2File($content, $file);
			} else {
				$tempFile = tempnam('/tmp', __FUNCTION__.'.');
				$handle = fopen($tempFile, 'r');
				self::write2File($content, $tempFile);
				copy($tempFile, $file);
				fclose($handle);
				unlink($tempFile);
			} //<-- end if -->

			return TRUE;
		} catch (Exception $e) {
			throw new Exception($e->getMessage().' from '.$this->className
				.'->'.__FUNCTION__.'() line '.__LINE__
			);
		} //<-- end try -->
	} //<-- end function -->

	/***************************************************************************
	 * Returns an array from csv data
	 *
	 * @param 	string 	$csvContent		csv text or path to a csv file
	 * @param 	boolean	$file 			is $csvContent a file path?
	 * @param 	string 	$fieldDelimiter the csv field delimiter
	 * @return 	array	$content		array of csv data
	 * @throws 	Exception if $csvFile does not exist
	 **************************************************************************/
	public function csv2Array($csvContent, $fieldDelimiter = ',', $file = TRUE){
		try {
			if ($file) {
				$csvFile = $csvContent;

				if (!file_exists($csvFile)) {
					throw new Exception('File '.$csvFile.' does not exist'.
						' from '.$this->className.'->'.__FUNCTION__.'() line '.
						__LINE__
					);
				}

				$tempFile = self::makeLFLineEndings($csvFile);
				$handle = fopen($tempFile, 'r');
				unlink($tempFile);
			} else { // not a file
				$csvContent = self::lines2Array($csvContent);
			} //<-- end if -->

			if ($file) {
				while (($data = fgetcsv($handle, 1000, $fieldDelimiter))
					!== FALSE)
				{
					$content[] = $data;
				} //<-- end while -->

				fclose($handle);
			} else { // not a file
				foreach ($csvContent as $data) {
					$content[] = str_getcsv($data, $fieldDelimiter);
				} //<-- end while -->
			} //<-- end if -->

			return $content;
		} catch (Exception $e) {
			throw new Exception($e->getMessage().' from '.$this->className
				.'->'.__FUNCTION__.'() line '.__LINE__
			);
		} //<-- end try -->
	} //<-- end function -->

	/***************************************************************************
	 * Converts an array to string while adding and extra string to beginning
	 * and end of each element
	 *
	 * @param 	array 	$content	array to convert
	 * @param 	string 	$extra		string to add to the beginning and end of
	 *								each array element
	 * @param 	string 	$delimiter	character to seperate each arrayelement
	 * @return 	string	$content	content formatted on 1 line with the extra
	 *								string added to the beginning and end of
	 *								each array element
	 * @throws 	Exception if $content is not an array
	 **************************************************************************/
	public function extraImplode($content, $extra = '\'', $delimiter = ' ') {
		if (!is_array($content)) {
			throw new Exception('Please use an array from '.
				$this->className.'->'.__FUNCTION__.'() line '.__LINE__
			);
		} else {
			try {
				$content = $extra.implode($extra.$delimiter.$extra, $content).
					$extra; // array to string
				return $content;
			} catch (Exception $e) {
				throw new Exception($e->getMessage().' from '.$this->className
					.'->'.__FUNCTION__.'() line '.__LINE__
				);
			} //<-- end try -->
		} //<-- end if -->
	} //<-- end function -->

	/***************************************************************************
	 * Returns an array from a multiline string
	 *
	 * @param 	string 	$content	a multiline string
	 * @return 	array	$content	array (one element from each line in the
	 *								string)
	 **************************************************************************/
	public function lines2Array($content) {
		try {
			$content = str_replace("\r\n", "\n", $content);
			$content = str_replace("\r", "\n", $content);
			$content = explode("\n", $content); // turn string to array
			array_pop($content); // remove last element since it is empty
			return $content;
		} catch (Exception $e) {
			throw new Exception($e->getMessage().' from '.$this->className.'->'.
				__FUNCTION__.'() line '.__LINE__
			);
		} //<-- end try -->
	} //<-- end function -->

	/***************************************************************************
	 * Reads input from STDIN
	 *
	 * @return 	string	$string	data read from STDIN
	 * @throws 	Exception if there is no input
	 **************************************************************************/
	public function readSTDIN() {
		try {
			$string = NULL;
			$handle = fopen('php://stdin', 'r');

			while (!feof($handle)) {
				$string .= fgets($handle, 1024);
			} //<-- end while -->

			fclose($handle);

			if (!$string) {
				throw new Exception('No data read from STDIN.');
			} else {
				return $string;
			} //<-- end if -->
		} catch (Exception $e) {
			throw new Exception($e->getMessage().' from '.$this->className.'->'.
				__FUNCTION__.'() line '.__LINE__
			);
		} //<-- end try -->
	} //<-- end function -->

	/***************************************************************************
	 * Creates an array by using one array for keys and another for its values
	 * Truncates/fills values if the number of elements for each array isn't
	 * equal.
	 *
	 * @param 	array 	$keys	the keys
	 * @param 	array 	$values	the values
	 * @return 	string	$string	data read from STDIN
	 * @throws 	Exception if there is no input
	 **************************************************************************/
	public function safeArrayCombine($keys, $values) {
		try {
			$combinedArray = array();
			$keyCount = count($keys);
			$valueCount = count($values);
			$difference = $keyCount - $valueCount;

			if ($difference > 0) {
				for ($i = 0; $i < $difference; $i++) {
					$values[] = $values[$valueCount - 1];
				}
			}

			for ($i=0, $keyCount; $i < $keyCount; $i++) {
				$combinedArray[$keys[$i]] = $values[$i];
			}

			return $combinedArray;
		} catch (Exception $e) {
			throw new Exception($e->getMessage().' from '.$this->className.'->'.
				__FUNCTION__.'() line '.__LINE__
			);
		} //<-- end try -->
	} //<-- end function -->

	/***************************************************************************
	 * Case insensitive array search.
	 *
	 * @param 	mixed 	$needle		the searched value
	 * @param 	array 	$haystack	the array to search
	 * @return 	string	$string		TRUE/FALSE
	 * @throws 	Exception if there is no input
	 **************************************************************************/
	public function in_arrayi($needle, $haystack) {
		return in_array(strtolower($needle),
			array_map('strtolower', $haystack)
		);
	}

	/***************************************************************************
	 * Hashes the contents of an array
	 *
	 * @param 	array 	$content	the array containing the content to hash
	 * @param 	string 	$hashKey	the key of the element to hash
	 * @param 	string 	$algo		the hashing algorithm to use
	 *
	 * supported algorithms:
	 * adler32; crc32; crc32b; gost; haval128,3; haval128,4; haval128,5;
	 * haval160,3; haval160,4; haval160,5; haval192,3; haval192,4; haval192,5;
	 * haval224,3; haval224,4; haval224,5; haval256,3; haval256,4; haval256,5;
	 * md2; md4; md5; ripemd128; ripemd160; ripemd256; ripemd320; sha1; sha256;
	 * sha384; sha512; snefru; tiger128,3; tiger128,4; tiger160,3; tiger160,4;
	 * tiger192,3; tiger192,4; whirlpool
	 *
	 * @throws 	Exception if $hashKey does not exist
	 **************************************************************************/
	public function hashArray(&$content, $hashKey, $algo = 'md5') {
		if(!array_key_exists($hashKey, current($content))) {
			throw new Exception('Key \''.$hashKey.'\' not found from '.
				$this->className.'->'.__FUNCTION__.'() line '.__LINE__
			);
		} else {
			try {
				foreach ($content as $key => $value) {
					$content[$key][$hashKey] = hash($algo, $value[$hashKey]);
				}

			} catch (Exception $e) {
				throw new Exception($e->getMessage().' from '.$this->className.
					'->'.__FUNCTION__.'() line '.__LINE__
				);
			} //<-- end try -->
		} //<-- end if -->
	} //<-- end function -->

	/***************************************************************************
	 * Delete elements of a multidimensional array if all the sub-arrays are
	 * empty
	 *
	 * @param 	array 	$content	multi-dimensional array
	 * @throws 	Exception if $content is not a multi-dimensional array
	 **************************************************************************/
	public function trimArray(&$content) {
		if (!is_array(current($content))) {
			throw new Exception('Please use a multi-dimensional array'.
				'from '.$this->className.'->'.__FUNCTION__.'() line '.
				__LINE__
			);
		} else {
			try {
				// loop through each array
				$count = count($content);

				for ($i = 0; $i < $count; $i++) {
					$last = count($content[$i]) - 1;

					foreach ($content[$i] as $subKey => $subValue) {
						if (!empty($subValue)) {
							continue 2; // go to next array
						}

						if ($subKey == $last) {
							array_splice($content, $i, 1);
							$i--;
							$count--;
						}
					} //<-- end foreach -->
				} //<-- end foreach -->
			} catch (Exception $e) {
				throw new Exception($e->getMessage().' from '.$this->className
					.'->'.__FUNCTION__.'() line '.__LINE__
				);
			} //<-- end try -->
		} //<-- end if -->
	} //<-- end function -->

	/***************************************************************************
	 * Returns the first set of completely non-null sub-arrays or the first
	 * sub-array if none are non-null
	 *
	 * @param 	array 	$content	multi-dimensional array
	 * @throws 	Exception if $content is not a multi-dimensional array
	 **************************************************************************/
	public function getNonNull($content) {
		if (!is_array(current($content))) {
			throw new Exception('Please use a multi-dimensional array'.
				'from '.$this->className.'->'.__FUNCTION__.'() line '.
				__LINE__
			);
		} else {
			try {
				// loop through each array
				$count = count($content);

				for ($i = 0; $i < $count; $i++) {
					$lastkey = array_pop(array_keys($content[$i]));

					foreach ($content[$i] as $subKey => $subValue) {

						if (is_null($subValue)) {
							continue 2; // go to next array
						}

						if ($subKey == $lastkey) {
							return $content[$i];
						}
					} //<-- end foreach -->

					return $content[0];
				} //<-- end foreach -->

			} catch (Exception $e) {
				throw new Exception($e->getMessage().' from '.$this->className
					.'->'.__FUNCTION__.'() line '.__LINE__
				);
			} //<-- end try -->
		} //<-- end if -->
	} //<-- end function -->

	/***************************************************************************
	 * Adds elements to a multidimensional array so that each sub-array is as
	 * long as the first sub-array
	 *
	 * @param 	array 	$content	multi-dimensional array
	 * @throws 	Exception if $content is not a multi-dimensional array
	 **************************************************************************/
	public function lengthenArray(&$content) {
		if (!is_array(current($content))) {
			throw new Exception('Please use a multi-dimensional array'.
				'from '.$this->className.'->'.__FUNCTION__.'() line '.
				__LINE__
			);
		} else {
			try {
				$count = count(current($content));

				// loop through each array
				foreach ($content as $key => $values) {
					$num = $count - count($values);

					if ($num > 0) { // check that arrays are same size
						for ($i = 0; $i < $num; $i++) {
							array_push($content[$key], '');
						} //<-- end for -->
					} //<-- end if -->
				} //<-- end foreach -->
			} catch (Exception $e) {
				throw new Exception($e->getMessage().' from '.$this->className
					.'->'.__FUNCTION__.'() line '.__LINE__
				);
			} //<-- end try -->
		} //<-- end if -->
	} //<-- end function -->

	/***************************************************************************
	 * Performs array_combine() on a multi-dimensional array using the first
	 * element for the keys and the remaining elements as the values
	 *
	 * @param 	array 	$content	of the following form:
	 * 								$content = array(
	 *									array($key1, $key2, $key3),
	 *									array($value1, $value2, $value3),
	 *									array($value4, $value5, $value6))
	 *
	 * @return 	array	$newContent	of the following form:
	 * 								$content = array(
	 *								array($key1 => $key1,
	 *									$key2 => $key2,
	 *									$key3 => $key3),
	 * 								array($key1 => $value1,
	 *									$key2 => $value2,
	 *									$key3 => $value3),
	 *								array($key1 => $value4,
	 *									$key2 => $value5,
	 *									$key3 => $value6))
	 *
	 * @throws 	Exception if $content is not a multi-dimensional array
	 **************************************************************************/
	public function arrayInsertKey($content) {
		if (!is_array(current($content))) {
			throw new Exception('Please use a multi-dimensional array'.
				'from '.$this->className.'->'.__FUNCTION__.'() line '.
				__LINE__
			);
		} else {
			try {
				$maxElements = count($content);
				$maxValues = count(current($content));

				// loop through each array
				foreach ($content as $key => $values) {
					// check that arrays are same size
					if (count($values) != $maxValues) {
						throw new Exception('Array '.$key.' is wrong size');
					} //<-- end if -->
				} //<-- end for -->

				$keys = $content[0]; // get key names

				// loop through each array
				foreach ($content as $values) {
					$newContent[] = array_combine($keys, $values);
				} //<-- end for loop through each array -->

				return $newContent;
			} catch (Exception $e) {
				throw new Exception($e->getMessage().' from '.$this->className
					.'->'.__FUNCTION__.'() line '.__LINE__
				);
			} //<-- end try -->
		} //<-- end if -->
	} //<-- end function -->

	/***************************************************************************
	 * Recursively returns all defined variables
	 *
	 * @param 	array 	$ignoreList 	the variables to ignore
	 * @return 	array 	$definedVars	defined variables not in the ignore list
	 **************************************************************************/
	public function getVars($vars, $ignoreList = NULL) {
		try {
			if (empty($ignoreList)) {
				$ignoreList = $this->varIgnoreList;
			} //<-- end if -->

			foreach ($vars as $key => $val) {
				if ($key === 0
					|| (!in_array($key, $ignoreList))
					&& !is_null($val)
				) {
					if (is_array($val)) {
						$definedVars[$key] = self::getVars($val);
					} elseif (is_string($val) || is_numeric($val)) {
						$definedVars[$key] = $val;
					} //<-- end if -->
				} //<-- end if -->
			} //<-- end foreach -->

			return $definedVars;
		} catch (Exception $e) {
			throw new Exception($e->getMessage().' from '.$this->className.'->'.
				__FUNCTION__.'() line '.__LINE__
			);
		} //<-- end try -->
	} //<-- end function -->

	/***************************************************************************
	 * Returns the filename without extension of a file
	 *
	 * @param 	string 	$file 	a filename or the path to a file
	 * @return 	string	$base	filename without extension
	 * @throws 	Exception if an empty value is passed
	 **************************************************************************/
	public function getBase($file) {
		if (empty($file)) {
			throw new Exception('Empty file passed from '.$this->className.'->'.
				__FUNCTION__.'() line '.__LINE__
			);
		} else {
			try {
				$base = pathinfo($file, PATHINFO_FILENAME);
				return $base;
			} catch (Exception $e) {
				throw new Exception($e->getMessage().' from '.$this->className
					.'->'.__FUNCTION__.'() line '.__LINE__
				);
			} //<-- end try -->
		} //<-- end if -->
	} //<-- end function -->

	/***************************************************************************
	 * Returns the full path to files in the current directory
	 *
	 * @param 	array 	$files 	a file in the current directory
	 * @return 	string	$base	filename without extension
	 * @throws 	Exception if $files is not an array
	 **************************************************************************/
	public function getFullPath($files) {
		if (!is_array($files)) {
			throw new Exception('Please use an array from '.
				$this->className.'->'.__FUNCTION__.'() line '.__LINE__
			);
		} else {
			try {
				$dir = getcwd();

				foreach ($files as $key => $value) {
					if (strpos($value, '/') === FALSE) {
						$files[$key] = $dir.'/'.$value;
					} //<-- end if -->
				} //<-- end foreach -->

				return $files;
			} catch (Exception $e) {
				throw new Exception($e->getMessage().' from '.$this->className
					.'->'.__FUNCTION__.'() line '.__LINE__
				);
			} //<-- end try -->
		} //<-- end if -->
	} //<-- end function -->

	/***************************************************************************
	 * Reads the contents of a given file
	 *
	 * @param 	string 	$file 		a filename or the path to a file
	 * @return 	string	$content	the file contents
	 * @throws 	Exception if $file does not exist
	 **************************************************************************/
	public function readFile($file) {
		if (!file_exists($file)) {
			throw new Exception('File '.$file.' does not exist from '.
				$this->className.'->'.__FUNCTION__.'() line '.__LINE__
			);
		} else {
			try {
				$handle 	= fopen($file, 'r');
				$string 	= NULL;

				while (!feof($handle)) {
					$string .= fgets($handle, 1024);
				} //<-- end while -->

				fclose($handle);
				return $string;
			} catch (Exception $e) {
				throw new Exception($e->getMessage().' from '.$this->className
					.'->'.__FUNCTION__.'() line '.__LINE__
				);
			} //<-- end try -->
		} //<-- end if -->
	} //<-- end function -->

	/***************************************************************************
	 * Writes a contents of a given file to a new file with LF line endings
	 *
	 * @param 	string 	$file 		a filename or the path to a file
	 * @return 	string	$tempFile	path to the temporary file created
	 * @throws 	Exception if $file does not exist
	 **************************************************************************/
	public function makeLFLineEndings($file) {
		if (!file_exists($file)) {
			throw new Exception('File '.$file.' does not exist from '.
				$this->className.'->'.__FUNCTION__.'() line '.__LINE__
			);
		} else {
			try {
				$tempFile	= tempnam('/tmp', __FUNCTION__.'.');
				$string 	= self::readFile($file);
				$string 	= str_replace("\r\n", "\n", $string);
				$string 	= str_replace("\r", "\n", $string);
				self::write2File($string, $tempFile);
				return $tempFile;
			} catch (Exception $e) {
				throw new Exception($e->getMessage().' from '.$this->className
					.'->'.__FUNCTION__.'() line '.__LINE__
				);
			} //<-- end try -->
		} //<-- end if -->
	} //<-- end function -->

	/***************************************************************************
	 * Performs a number or date format on the elements of a given key in a
	 * multi-dimensional array suitable for import into a sqlite database
	 *
	 * @param 	array 	$content	of the following form:
	 * 								$content = array(
	 *									array($key1 => $value1,
	 *										$key2 => $value2,
	 *										$key3 => $value3),
	 *									array($key1 => $value4,
	 *										$key2 => $value5,
	 *										$key3 => $value6))
	 *
	 * @param 	string 	$formatKey	the key whose values you want to format
	 * @param 	string 	$format		the type of format to apply the (i.e.
	 *								'number' or 'date')
	 *
	 * @throws 	Exception if $content is not a multi-dimensional array
	 * @throws 	Exception if $format is invalid
	 **************************************************************************/
	public function formatArray(&$content, $formatKey, $format) {
		if (!is_array(current($content))) {
			throw new Exception('Please use a multi-dimensional array from '.
				$this->className.'->'.__FUNCTION__.'() line '.__LINE__
			);
		} else {
			try {
				switch ($format){
					case 'number':
						foreach ($content as $key => $row) {
							$number = $row[$formatKey];
							$number = str_replace(',', '', $number) + 0;
							$number = number_format($number, 2, '.', '');
							$content[$key][$formatKey] = $number;
						} //<-- end foreach -->

						break;

					case 'date':
						foreach ($content as $key => $row) {
							$date = $row[$formatKey];
							// format to yyyy-mm-dd
							$date = date("Y-m-d", strtotime($date));
							$content[$key][$formatKey] = $date;
						} //<-- end foreach -->

						break;

					default:
						throw new Exception('Wrong format entered. Please type'.
							' \'number\' or \'date\'.'
						);
				} //<-- end switch -->
			} catch (Exception $e) {
				throw new Exception($e->getMessage().' from '
					.$this->className.'->'.__FUNCTION__.'() line '.__LINE__
				);
			} //<-- end try -->
		} //<-- end if -->
	} //<-- end function -->

	/***************************************************************************
	 * Sort a multidimensional array by the value of a given subkey
	 *
	 * @param 	array 	$array	the array to sort
	 * @param 	string 	$key	the subkey to sort by
	 * @return 	array	$content	new array with moved values
	 **************************************************************************/
	public function arraySortBySubValue(&$array, $key) {
		if(!array_key_exists($key, current($array))) {
			throw new Exception('Key \''.$key.'\' not found from '.
				__CLASS__.'->'.__FUNCTION__.'() line '.__LINE__
			);
		} else {
			try {
				$cmp = function (array $a, array $b) use ($key) {
					return strcmp($a[$key], $b[$key]);
				};

				usort($array, $cmp);
			} catch (Exception $e) {
				throw new Exception($e->getMessage().' from '.$this->className
					.'->'.__FUNCTION__.'() line '.__LINE__
				);
			} //<-- end try -->
		} //<-- end if -->
	} //<-- end function -->

	/***************************************************************************
	 * Move a given element to the beginning of an array
	 *
	 * @param 	array 	$array	the array to perform the move on
	 * @param 	string 	$key	the the key of the element to move
	 **************************************************************************/
	public function arrayMove(&$array, $key) {
		if(!array_key_exists($key, $array)) {
			throw new Exception('Key '.$key.' not found from '.
				$this->className.'->'.__FUNCTION__.'() line '.__LINE__
			);
		} else {
			try {
				$append = $array[$key];
				array_splice($array, $key, 1);
				array_unshift($array, $append);
			} catch (Exception $e) {
				throw new Exception($e->getMessage().' from '.$this->className
					.'->'.__FUNCTION__.'() line '.__LINE__
				);
			} //<-- end try -->
		} //<-- end if -->
	} //<-- end function -->

	/***************************************************************************
	 * Recursively replaces all NULL elements with 0 in an array (by reference)
	 * if a following element is non-null
	 * @param 	array 	$content	the array to perform the replacement on
	 * @param 	string 	$replace	the replacement value that replaces $needle
	 *								(an array may be used to designate multiple
	 *								replacements)
	 **************************************************************************/
	public function arrayFillMissing(&$content) {
		try {
			$count = count($content);
			$keys = array_keys($content);

			for ($i = 0; $i < $count; $i++) {
				$currkey = $keys[$i];

				// If it's not an array, continue checking
				if (!is_array($content[$currkey])) {
					if (is_null($content[$currkey])) {
						if ($i != 0 && $i != $count - 1) {
							$prevkey = $keys[$i - 1];
							$nextkey = $keys[$i + 1];

							if (!is_null($content[$nextkey])) {
								$content[$currkey] = 0;
							} //<-- end if -->

							if (!is_null($content[$prevkey])) {
								$pass = FALSE;

								for ($j = $i; $j < $count; $j++) {
									// check to see if there is at least one
									// additional non-null value following
									if (!is_null($content[$keys[$j]])) {
										$pass = TRUE;
										break;
									} //<-- end if -->
								} //<-- end for -->

								if ($pass) {
									$content[$currkey] = 0;
								} else {
									// no more non-null values so exit loop
									break;
								} //<-- end if -->
							} //<-- end if -->
						} //<-- end if -->
					} //<-- end if -->
				} else { // it IS an array, so recurse
					self::arrayFillMissing($content[$currkey]);
				} //<-- end if -->
			} //<-- end foreach -->
		} catch (Exception $e) {
			throw new Exception($e->getMessage().' from '.$this->className.'->'.
				__FUNCTION__.'() line '.__LINE__
			);
		} //<-- end try -->
	} //<-- end function -->

	/***************************************************************************
	 * Recursively replaces all NULLs with $replace in an array (by reference)
	 * @param 	array 	$content	the array to perform the replacement on
	 * @param 	string 	$replace	the replacement value that replaces $needle
	 *								(an array may be used to designate multiple
	 *								replacements)
	 **************************************************************************/
	public function arrayReplaceNull(&$content, $replace) {
		try {
			foreach ($content as &$haystack) {
				// If it's not an array, replace it
				if (!is_array($haystack)) {
					if (is_null($haystack)) {
						$haystack = $replace;
					} //<-- end if -->
				} else { // it IS an array, so recurse
					self::arrayReplaceNull($haystack, $replace);
				} //<-- end if -->
			} //<-- end foreach -->
		} catch (Exception $e) {
			throw new Exception($e->getMessage().' from '.$this->className.'->'.
				__FUNCTION__.'() line '.__LINE__
			);
		} //<-- end try -->
	} //<-- end function -->

	/***************************************************************************
	 * Recursively replaces all occurrences of $needle with $replace in an
	 * an array (by reference)
	 *
	 * @param 	array 	$content	the array to perform the replacement on
	 * @param 	string 	$needle		the value being searched for (an array may
	 *								be used to designate multiple needles)
	 * @param 	string 	$replace	the replacement value that replaces $needle
	 *								(an array may be used to designate multiple
	 *								replacements)
	 **************************************************************************/
	public function arraySubstituteBr(&$content, $needle, $replace) {
		try {
			foreach ($content as &$haystack) {
				if (!is_array($haystack)) { // If it's not an array, sanitize it
					$haystack = str_replace($needle, $replace, $haystack);
				} else { // it IS an array, so recurse
					self::arraySubstituteBr($haystack, $needle, $replace);
				} //<-- end if -->
			} //<-- end foreach -->
		} catch (Exception $e) {
			throw new Exception($e->getMessage().' from '.$this->className.'->'.
				__FUNCTION__.'() line '.__LINE__
			);
		} //<-- end try -->
	} //<-- end function -->

	/***************************************************************************
	 * Recursively replaces all occurrences of $needle with $replace on
	 * elements in an array
	 *
	 * @param 	array 	$content	the array to perform the replacement on
	 * @param 	string 	$needle		the value being searched for (an array may
	 *								be used to designate multiple needles)
	 * @param 	string 	$replace	the replacement value that replaces $needle
	 *								(an array may be used to designate multiple
	 *								replacements)
	 *
	 * @return 	array	$newContent	new array with replaced values
	 **************************************************************************/
	public function arraySubstitute($content, $needle, $replace) {
		try {
			foreach ($content as $haystack) {
				if (!is_array($haystack)) { // If it's not an array, sanitize it
					$newContent[] = str_replace($needle, $replace, $haystack);
				} else { // it IS an array, so recurse
					$newContent[] = self::arraySubstitute($haystack,
						$needle, $replace);
				} //<-- end if -->
			} //<-- end foreach -->

			return $newContent;
		} catch (Exception $e) {
			throw new Exception($e->getMessage().' from '.$this->className.'->'.
				__FUNCTION__.'() line '.__LINE__
			);
		} //<-- end try -->
	} //<-- end function -->

	/***************************************************************************
	 * Converts data to xml compliant input
	 *
	 * @param 	string 	$content the content to clean
	 * @return 	string 	$content the cleaned content
	 * @throws 	Exception if $content is empty
	 **************************************************************************/
	public function xmlize($content) {
		if (empty($content)) { // check to make sure $content isn't empty
			throw new Exception('Empty value passed from '.
				$this->className.'->'.__FUNCTION__.'() line '.__LINE__
			);
		} else {
			try {
				$invalid_text = array('&', '<', '>', '\r\n', '\n');
				$valid_text = array('&', '<', '>', ' ', ' ');
				$content = str_replace($invalid_text, $valid_text, $content);
				return $content;
			} catch (Exception $e) {
				throw new Exception($e->getMessage().' from '.$this->className.
					'->'.__FUNCTION__.'() line '.__LINE__
				);
			} //<-- end try -->
		} //<-- end if -->
	} //<-- end function -->

	/***************************************************************************
	 * Writes an array to a csv file (overwrites file if it exists)
	 *
	 * @param 	string 	$content 		the data to write to the file
	 * @param 	string 	$csvFile 		the path to a csv file
	 * @param 	string 	$fieldDelimiter the csv field delimiter
	 * @return 	boolean	TRUE
	 **************************************************************************/
	public function overwriteCSV($content, $csvFile, $fieldDelimiter = ',') {
		try {
			if (!file_exists($csvFile)) {
				self::array2CSV($content, $csvFile, $fieldDelimiter);
			} else {
				//$tempFile = self::makeLFLineEndings($csvFile);
				$tempFile = tempnam('/tmp', __FUNCTION__.'.');
				$handle = fopen($tempFile, 'r');
				self::array2CSV($content, $tempFile, $fieldDelimiter);
				copy($tempFile, $csvFile);
				fclose($handle);
				unlink($tempFile);
			} //<-- end if -->

			return TRUE;
		} catch (Exception $e) {
			throw new Exception($e->getMessage().' from '.$this->className
				.'->'.__FUNCTION__.'() line '.__LINE__
			);
		} //<-- end try -->
	} //<-- end function -->

	/***************************************************************************
	 * Writes an array to a csv file
	 *
	 * @param 	string 	$content 		the data to write to the file
	 * @param 	string 	$fieldDelimiter the csv field delimiter
	 * @param 	string 	$csvFile 		the path to an empty or non existing
	 *									csv file
	 * @return 	boolean	TRUE
	 * @throws 	Exception if $csvFile exists or is non-empty
	 **************************************************************************/
	public function array2CSV($content, $csvFile, $fieldDelimiter = ',') {
		if (file_exists($csvFile) && filesize($csvFile) != 0) {
			throw new Exception('File '.$csvFile.' already exists from '.
				$this->className.'->'.__FUNCTION__.'() line '.__LINE__
			);
		} else {
			try {
				$handle = fopen($csvFile, 'w');

				foreach ($content as $fields) {
					$length = fputcsv($handle, $fields, $fieldDelimiter);
				} //<-- end foreach -->

				fclose($handle);

				if ($this->verbose) {
					fwrite(STDOUT, "wrote $length characters to $csvFile!\n");
				} //<-- end if -->

				return TRUE;
			} catch (Exception $e) {
				throw new Exception($e->getMessage().' from '.$this->className
					.'->'.__FUNCTION__.'() line '.__LINE__
				);
			} //<-- end try -->
		} //<-- end if -->
	} //<-- end function -->
} //<-- end class -->
?>


text:
package alluxio.client.cli.fsadmin.command;

import alluxio.ProjectConstants;
import alluxio.cli.fsadmin.command.ReportCommand;
import alluxio.client.cli.fsadmin.AbstractFsAdminShellTest;
import alluxio.conf.PropertyKey;
import alluxio.conf.ServerConfiguration;
import alluxio.util.network.NetworkAddressUtils;

import org.hamcrest.CoreMatchers;
import org.junit.Assert;
import org.junit.Test;

/**
 * Tests for report command.
 */
public final class ReportCommandIntegrationTest extends AbstractFsAdminShellTest {
  @Test
  public void masterNotRunning() throws Exception {
    mLocalAlluxioCluster.stopMasters();
    int ret = mFsAdminShell.run("report");
    Assert.assertNotEquals(0, ret);
  }

  @Test
  public void reportCategoryInvalid() {
    mFsAdminShell.run("report", "invalidCategory");
    String expected = String.join("\n",
        ReportCommand.usage(),
        ReportCommand.description(),
        "report category is invalid.") + "\n";
    Assert.assertEquals(expected, mOutput.toString());
  }

  @Test
  public void reportSummary() {
    int ret = mFsAdminShell.run("report", "summary");
    Assert.assertEquals(0, ret);
    String output = mOutput.toString();

    // Check if meta master values are available
    String expectedMasterAddress = NetworkAddressUtils
        .getConnectAddress(NetworkAddressUtils.ServiceType.MASTER_RPC,
            ServerConfiguration.global()).toString();
    Assert.assertThat(output, CoreMatchers.containsString(
        "Master Address: " + expectedMasterAddress));
    Assert.assertThat(output, CoreMatchers.containsString(
        "Web Port: " + ServerConfiguration.get(PropertyKey.MASTER_WEB_PORT)));
    Assert.assertThat(output, CoreMatchers.containsString(
        "Rpc Port: " + ServerConfiguration.get(PropertyKey.MASTER_RPC_PORT)));
    Assert.assertFalse(output.contains("Started: 12-31-1969 16:00:00:000"));
    Assert.assertThat(output, CoreMatchers.containsString(
        "Version: " + ProjectConstants.VERSION));
    Assert.assertThat(output, CoreMatchers.containsString(
        "Zookeeper Enabled: false"));

    // Check if block master values are available
    Assert.assertThat(output, CoreMatchers.containsString("Live Workers: 1"));
    Assert.assertFalse(output.contains("Total Capacity: 0B"));
  }

  @Test
  public void reportUfs() {
    int ret = mFsAdminShell.run("report", "ufs");
    Assert.assertEquals(0, ret);
    String output = mOutput.toString();
    Assert.assertThat(output,
        CoreMatchers.containsString("Alluxio under storage system information:"));
    Assert.assertThat(output,
        CoreMatchers.containsString("not read-only, not shared, properties={})"));
  }
}