Ejemplo n.º 1
0
    def test_deep_dict(self):
        filename = os.path.join(TEMPDIR, "cask_deep_dict.abc")

        # read in a simple scene with several shapes
        a = cask.Archive(deep_out())
        t = a.top

        # deep dict access
        self.assertEqual(t.children["A"].name, "A")
        self.assertEqual(t.children["A/B/C/D"].name, "D")
        self.assertEqual(t.children["A"].properties["a"].name, "a")
        self.assertEqual(t.children["A/B/C/D"].properties["a/b/c"].name, "c")
        self.assertRaises(KeyError, t.children.__getitem__, "A/B/C/Z")

        # property accessors
        x = t.children.values()[0]
        self.assertEqual(x.name, "A")
        self.assertEqual(x.properties["a/b/c/myprop"].values[0], "foo")

        # test deep set item on leaf node
        p = t.children["A/B/C/D/meshy"] = cask.PolyMesh()
        self.assertEqual(p.name, "meshy")
        self.assertEqual(p.type(), "PolyMesh")
        self.assertEqual(p.parent, t.children["A/B/C/D"])
        self.assertTrue("meshy" in t.children["A/B/C/D"].children.keys())
        self.assertEqual(len(p.children.keys()), 0)

        # another test
        patch = cask.NuPatch()
        t.children["A/B/C/D/patch"] = patch
        self.assertEqual(patch.name, "patch")
        self.assertEqual(patch.parent, t.children["A/B/C/D"])
        self.assertTrue("patch" in t.children["A/B/C/D"].children.keys())
        self.assertFalse("patch" in t.children.keys())
        self.assertEqual(len(patch.children.keys()), 0)

        # rename test
        patch.name = "nurby"
        self.assertFalse("patch" in t.children["A/B/C/D"].children.keys())
        self.assertTrue("nurby" in t.children["A/B/C/D"].children.keys())
        self.assertEqual(patch.parent, t.children["A/B/C/D"])
        self.assertEqual(t.children["A/B/C/D/nurby"], patch)
        self.assertRaises(KeyError, t.children.__getitem__, "A/B/C/D/patch")

        # test deep dict reassignment
        t.children["A/B/C/D/meshy"] = cask.Xform()
        p2 = t.children["A/B/C/D/meshy"]
        self.assertEqual(p2.name, "meshy")
        self.assertEqual(p2.parent, t.children["A/B/C/D"])
        self.assertFalse(p2.name in t.children.keys())
        self.assertEqual(len(p2.children.values()), 0)
        self.assertEqual(t.children["A/B/C/D/meshy"].type(), "Xform")
        self.assertEqual(p2.type(), "Xform")

        # test deep set item when middle node does not exist
        self.assertRaises(KeyError, t.children.__setitem__, "A/foo/C/D/bar",
                          cask.Xform())

        # write the archive
        a.write_to_file(filename)
Ejemplo n.º 2
0
    def test_reassign(self):
        filename = os.path.join(TEMPDIR, "cask_test_reassign.abc")

        a = cask.Archive()
        t = a.top
        t.children["xform"] = cask.Xform()
        t.properties["prop"] = cask.Property()
        self.assertEqual(t.children["xform"].type(), "Xform")
        self.assertEqual(t.properties["prop"].type(), "Property")

        # reassign object
        t.children["xform"] = cask.PolyMesh()
        self.assertEqual(t.children["xform"].type(), "PolyMesh")

        # rename object
        x = t.children["xform"]
        x.name = "meshy"
        self.assertRaises(KeyError, t.children.__getitem__, "xform")
        self.assertTrue("meshy" in t.children.keys())
        self.assertEqual(t.children["meshy"], x)

        # rename property
        p = t.properties["prop"]
        p.name = "new"
        self.assertRaises(KeyError, t.properties.__getitem__, "prop")
        self.assertEqual(t.properties.values()[0].name, "new")
        self.assertEqual(t.properties["new"], p)

        # another rename test
        x = cask.Xform()
        t.children["foo"] = x
        self.assertTrue("foo" in t.children.keys())
        self.assertEqual(x.path(), "/foo")
        x.name = "bar"
        self.assertEqual(x.path(), "/bar")
        self.assertFalse("foo" in t.children.keys())
        self.assertTrue("bar" in t.children.keys())
        self.assertEqual(x.archive(), a)

        # child of child rename/reassign test
        baz = x.children["baz"] = cask.Xform()
        self.assertEqual(baz.path(), "/bar/baz")
        baz.name = "zap"
        self.assertFalse("zap" in t.children.keys())
        self.assertEqual(baz.path(), "/bar/zap")
        self.assertTrue("zap" in x.children.keys())
        self.assertEqual(baz.type(), "Xform")

        # reassign child obj to PolyMesh
        x.children["zap"] = cask.PolyMesh()
        self.assertEqual(x.children["zap"].type(), "PolyMesh")

        # write to a file
        a.write_to_file(filename)
Ejemplo n.º 3
0
    def test_add_child(self):
        """Creates a simple cache with one mesh, then moves and copies it. 
        Resulting abc cache should look like this:

        ABC                                                                                                                                        
         |--x1
         |--x2
         |    `--meshy
         `--x3
             `--meshy
        """
        filename = os.path.join(TEMPDIR, "cask_add_child.abc")
        
        a = cask.Archive(mesh_out())
        meshy = a.top.children["meshy"]
        x1 = a.top.children["x1"] = cask.Xform()
        x2 = a.top.children["x2"] = cask.Xform()
        x3 = a.top.children["x3"] = cask.Xform()

        # test moving it and copying it
        x1.add_child(meshy)
        x2.add_child(meshy)
        x3.add_child(cask.copy(meshy))

        # export to a new filename
        a.write_to_file(filename)
        a.close()

        # test the new file
        a = cask.Archive(filename)
        self.assertEqual(set(a.top.children.keys()), set(["x1", "x2", "x3"]))
        
        x1 = a.top.children["x1"]
        x2 = a.top.children["x2"]
        x3 = a.top.children["x3"]
        
        # meshy should have been moved from x1->x2, and copied to x3
        self.assertEqual(len(x1.children), 0)
        self.assertEqual(len(x2.children), 1)
        self.assertEqual(len(x3.children), 1)

        m2 = x2.children["meshy"]
        m3 = x3.children["meshy"]

        # basic check to see if mesh points are the same
        self.assertEqual(m2.type(), "PolyMesh")
        self.assertEqual(m3.type(), "PolyMesh")
        self.assertEqual(m2.properties[".geom/P"].values,
                m3.properties[".geom/P"].values)
        a.close()
Ejemplo n.º 4
0
    def test_rename(self):
        filename = os.path.join(TEMPDIR, "cask_test_rename.abc")

        a = cask.Archive()
        t = a.top

        # create a new object and property
        t.children["foo"] = cask.Xform()
        t.properties["some"] = cask.Property()
        f = t.children.values()[0]
        p = t.properties.values()[0]
        self.assertEqual(f.name, "foo")
        self.assertEqual(p.name, "some")

        # rename them
        f.name = "bar"
        self.assertEqual(f.name, "bar")
        self.assertEqual(t.children.values()[0].name, "bar")
        p.name = "thing"
        self.assertEqual(p.name, "thing")
        self.assertEqual(t.properties.values()[0].name, "thing")

        # test for accessor updates
        self.assertEqual(t.children["bar"], f)
        self.assertRaises(KeyError, t.children.__getitem__, "foo")
        self.assertEqual(t.properties["thing"], p)
        self.assertRaises(KeyError, t.properties.__getitem__, "some")

        # write to a file
        a.write_to_file(filename)
Ejemplo n.º 5
0
    def test_write_mesh(self):
        filename = os.path.join(TEMPDIR, "cask_write_mesh.abc")
        
        # create empty archive, xform and polymesh
        a = cask.Archive()
        x = cask.Xform()
        p = cask.PolyMesh()

        # hierarchy assignment
        a.top.children["foo"] = x
        x.children["meshy"] = p

        # set sample values using wrapped sample methods
        x.set_scale(imath.V3d(1, 2, 3))

        # create alembic polymesh sample and set it on our polymesh
        uvsamp = alembic.AbcGeom.OV2fGeomParamSample(meshData.uvs, kFacevaryingScope) 
        nsamp = alembic.AbcGeom.ON3fGeomParamSample(meshData.normals, kFacevaryingScope)
        s = alembic.AbcGeom.OPolyMeshSchemaSample(meshData.verts, meshData.indices, 
                meshData.counts, uvsamp, nsamp)
        p.set_sample(s)

        # write to disk
        a.write_to_file(filename)
        self.assertTrue(os.path.isfile(filename))
Ejemplo n.º 6
0
    def test_issue_349(self):
        test_file = os.path.join(TEMPDIR, "cask_test_issue_349.abc")

        # create a new archive and some objects
        a = cask.Archive()
        xf = a.top.children["renderCamXform"] = cask.Xform()
        cam = xf.children["renderCamShape"] = cask.Camera()

        # add some sample data
        for i in range(24):
            samp = alembic.AbcGeom.XformSample()
            samp.setTranslation(imath.V3d(i, 2.0, 3.0))
            xf.set_sample(samp)

        # export it
        a.write_to_file(test_file)
        a.close()

        # read the test archive back in and verify results
        a = cask.Archive(test_file)
        xform = a.top.children["renderCamXform"]
        self.assertEqual(len(a.timesamplings), 2)
        self.assertEqual(xform.time_sampling_id, 1)
        self.assertEqual(len(xform.samples), 24)
        self.assertEqual(a.start_frame(), 0)
        self.assertEqual(a.end_frame(), 23)
Ejemplo n.º 7
0
    def test_child_bounds(self):
        filename_1 = os.path.join(TEMPDIR, "cask_child_bounds_1.abc")
        filename_2 = os.path.join(TEMPDIR, "cask_child_bounds_2.abc")
        filename_3 = os.path.join(TEMPDIR, "cask_child_bounds_3.abc")

        # create initial archive with initial value
        bounds = imath.Box3d(
            imath.V3d(1, 1, 1), imath.V3d(1, 1, 1)
        )
        a = cask.Archive()
        x = a.top.children["foo"] = cask.Xform()
        p = x.properties[".xform/.childBnds"] = cask.Property()
        p.set_value(bounds)
        self.assertEqual(p.values[0], bounds)
        a.write_to_file(filename_1)
        a.close()

        # verify export / value
        b = cask.Archive(filename_1)
        p = b.top.children["foo"].properties[".xform/.childBnds"]
        self.assertEqual(len(p.values), 1)
        self.assertEqual(p.values[0], bounds)
        self.assertEqual(p.metadata.get("interpretation"), "box")
        
        # set a new child bounds value and export
        bounds = imath.Box3d(
            imath.V3d(-5, -5, -5), imath.V3d(5, 5, 5)
        )
        p.values[0] = bounds
        self.assertEqual(p.values[0], bounds)
        b.write_to_file(filename_2)
        b.close()

        # verify the updated value in the export
        c = cask.Archive(filename_2)
        p = c.top.children["foo"].properties[".xform/.childBnds"]
        self.assertEqual(len(p.values), 1)
        self.assertEqual(p.values[0], bounds)
        self.assertEqual(p.metadata.get("interpretation"), "box")

        # reinitialize the property and export
        p = c.top.children["foo"].properties[".xform/.childBnds"] = cask.Property()
        p.set_value(bounds)
        c.write_to_file(filename_3)
        c.close()

        # re-verify the updated value in the export
        d = cask.Archive(filename_3)
        p = d.top.children["foo"].properties[".xform/.childBnds"]
        self.assertEqual(len(p.values), 1)
        self.assertEqual(p.values[0], bounds)
        self.assertEqual(p.metadata.get("interpretation"), "box")
Ejemplo n.º 8
0
    def test_paths(self):
        filepath = lights_out()
        a = cask.Archive(filepath)
        t = a.top
    
        # get some objects to test
        lightA = t.children["lightA"]
        lightB = t.children["lightB"]
        
        # test paths on objects
        self.assertEqual(a.path(), filepath)
        self.assertEqual(t.path(), "/")
        self.assertEqual(lightA.path(), "/lightA")
        self.assertEqual(lightB.path(), "/lightB")
        self.assertEqual(t.children[lightA.path()], lightA)

        # test paths on properties
        self.assertEqual(lightB.properties[".geom/.camera/.core"].path(), 
                            "/lightB/.geom/.camera/.core")

        # test paths on empty archive
        a = cask.Archive()
        t = a.top
        x = t.children["x"] = cask.Xform()
        y = x.children["y"] = cask.Xform()
        z = y.children["z"] = cask.Xform()
        p = z.properties["p"] = cask.Property()
        self.assertEqual(a.path(), None)
        self.assertEqual(t.path(), "/")
        self.assertEqual(x.path(), "/x")
        self.assertEqual(y.path(), "/x/y")
        self.assertEqual(z.path(), "/x/y/z")
        self.assertEqual(p.path(), "/x/y/z/p")

        # test reparenting
        p.parent = x
        self.assertEqual(p.path(), "/x/p")
Ejemplo n.º 9
0
    def test_issue_23(self):
        """github issue #23: preserve user properties"""

        test_file = os.path.join(TEMPDIR, "cask_test_issue_23.abc")
        test_file_2 = os.path.join(TEMPDIR, "cask_test_issue_23_2.abc")

        a = cask.Archive()
        x = a.top.children["x"] = cask.Xform()
        x.properties[".xform"] = cask.Property()

        # create the .userProperties compound prop
        up = x.properties[".xform"].properties[".userProperties"] = cask.Property()
        
        # create some user properties
        p1 = up.properties["foo"] = cask.Property()
        p1.set_value("bar")
        p2 = up.properties["bar"] = cask.Property()
        p2.set_value(1.0)

        # export it
        a.write_to_file(test_file)
        a.close()

        # read it back in and check for the user properties
        a = cask.Archive(test_file)
        x = a.top.children["x"]
        self.assertEqual(x.properties.keys(), [".xform"])
        self.assertEqual(x.properties[".xform"].properties.keys(), 
            [".userProperties"])
        up = x.properties[".xform/.userProperties"]

        # assert the values are the same
        self.assertEqual(len(up.properties), 2)
        self.assertEqual(up.properties["foo"].values[0], "bar")
        self.assertEqual(up.properties["bar"].values[0], 1.0)

        # use the alembic python api directly
        ph = a.top.children["x"].schema.getUserProperties().propertyheaders
        self.assertEqual(len(ph), 2)
        self.assertEqual(ph[0].getName(), "foo")
        self.assertEqual(ph[1].getName(), "bar")

        # recreate these properties and re-export
        # (test for AttributeError: 'OObject' object has no attribute 'getSchema')
        p1 = up.properties["foo"] = cask.Property()
        p2 = up.properties["bar"] = cask.Property()
        p1.set_value("baz")
        p2.set_value(2.0)
        a.write_to_file(test_file_2)
Ejemplo n.º 10
0
    def test_insert_node(self):
        filename = os.path.join(TEMPDIR, "cask_insert_node.abc")

        # test inerting a node into the hierarchy at the top
        a = cask.Archive(mesh_out())
        
        # insert a new xform between two nodes
        r = cask.Xform()
        m = a.top.children["meshy"]
        a.top.children["root"] = r
        r.children["meshy"] = m

        # write to disk
        a.write_to_file(filename)
        self.assertTrue(os.path.isfile(filename))
Ejemplo n.º 11
0
    def test_frame_range(self):
        filename = os.path.join(TEMPDIR, "cask_frame_range.abc")

        # create a new archive and some objects
        a = cask.Archive()
        xf = a.top.children["renderCamXform"] = cask.Xform()

        # set the start frame to 1001
        a.set_start_frame(1001)

        self.assertEqual(a.start_frame(), 1001)
        self.assertEqual(a.start_time(), 1001 / float(a.fps))

        # add some sample data
        for i in range(24):
            samp = alembic.AbcGeom.XformSample()
            samp.setTranslation(imath.V3d(i, 2.0, 3.0))
            xf.set_sample(samp)

        # export it
        a.write_to_file(filename)
Ejemplo n.º 12
0
    def test_write_geom(self):
        filename = os.path.join(TEMPDIR, "cask_write_geom.abc")

        # create empty archive and put some objects in it
        a = cask.Archive()

        # create one of each geom class
        a.top.children["xform"] = cask.Xform()
        a.top.children["polymesh"] = cask.PolyMesh()
        a.top.children["subd"] = cask.SubD()
        a.top.children["faceset"] = cask.FaceSet()
        a.top.children["curve"] = cask.Curve()
        a.top.children["camera"] = cask.Camera()
        a.top.children["nupatch"] = cask.NuPatch()
        a.top.children["material"] = cask.Material()
        a.top.children["light"] = cask.Light()
        a.top.children["points"] = cask.Points()

        # export the archive
        a.write_to_file(filename)
        self.assertTrue(os.path.isfile(filename))
Ejemplo n.º 13
0
    def test_issue_26(self):
        """github issue #26: verify .ops and .vals pod and extent"""
        
        test_file_1 = os.path.join(TEMPDIR, "cask_test_issue_26.abc")

        # create some scalar properties with array values
        a = cask.Archive()
        a.top.children["foo"] = cask.Xform()
        p1 = a.top.children["foo"].properties["p1"] = cask.Property()
        p2 = a.top.children["foo"].properties["p2"] = cask.Property()
        p1.set_value(imath.UnsignedCharArray(6))
        p2.set_value(imath.DoubleArray(12))
        a.write_to_file(test_file_1)
        a.close()

        # open the exported file and assert properties are scalar
        a = cask.Archive(test_file_1)
        p1 = a.top.children["foo"].properties["p1"]
        p2 = a.top.children["foo"].properties["p2"]
        self.assertTrue(p1.iobject.isScalar())
        self.assertTrue(p2.iobject.isScalar())
        a.close()
Ejemplo n.º 14
0
    def test_write_basic(self):
        filename = os.path.join(TEMPDIR, "cask_write_basic.abc")

        # create empty archive
        a = cask.Archive()
        self.assertEqual(len(a.top.children), 0)
        
        # create xform object named foo and make it a child of top
        f = a.top.children["foo"] = cask.Xform()
        self.assertEqual(len(a.top.children), 1)
        self.assertEqual(a.top.children.values()[0].name, "foo")

        # create some simple properties
        b = f.properties["bar"] = cask.Property()
        a.top.children["foo"].properties["bar"].set_value("hello")
        f.properties["baz"] = cask.Property()
        a.top.children["foo"].properties["baz"].set_value(42.0)

        # check to make sure object() returns the right thing
        self.assertEqual(b.object(), f)

        # write to disk
        a.write_to_file(filename)
        self.assertTrue(os.path.isfile(filename))
Ejemplo n.º 15
0
    def test_pod_extent(self):
        filename = os.path.join(TEMPDIR, "cask_pod_extent.abc")

        extent = 5
        v = imath.UnsignedCharArray(extent)
        for i in range(0, extent):
            v[i] = i

        a = cask.Archive()

        # create test properties
        foo = a.top.children["foo"] = cask.Xform()
        bar = foo.properties["bar"] = cask.Property()
        baz = foo.properties["baz"] = cask.Property()
        qux = foo.properties["qux"] = cask.Property()
        quux = foo.properties["quux"] = cask.Property()
        garply = foo.properties["garply"] = cask.Property()
        waldo = foo.properties["waldo"] = cask.Property()
        fred = foo.properties["fred"] = cask.Property()
        color = foo.properties["color"] = cask.Property()
        color.metadata["interpretation"] = "rgb"
        
        # set test values
        v = imath.UnsignedCharArray(5)
        for i in range(0, 5):
            v[i] = i
        bar.set_value(v)
        baz.set_value(["a", "b", "c"])
        qux.set_value(imath.Box3d())
        quux.set_value(imath.M33d())
        garply.set_value(imath.M44d())
        waldo.set_value(1)
        fred.set_value([1, 2, 3, 4])
        color.set_value(imath.Color3f(1, 2, 3))
       
        # export
        a.write_to_file(filename)
        a.close()

        # reimport the test file
        a = cask.Archive(filename)

        # recover the test properties
        foo = a.top.children["foo"]
        bar = foo.properties["bar"]
        baz = foo.properties["baz"]
        qux = foo.properties["qux"]
        quux = foo.properties["quux"]
        garply = foo.properties["garply"]
        waldo = foo.properties["waldo"]
        fred = foo.properties["fred"]
        color = foo.properties["color"]
        
        # assert pod, extent values
        self.assertEqual(bar.extent(), 5)
        self.assertEqual(bar.pod(), alembic.Util.POD.kUint8POD)
        self.assertEqual(bar.values[0], v)
        self.assertEqual(baz.extent(), 1)
        self.assertEqual(baz.pod(), alembic.Util.POD.kStringPOD)
        self.assertEqual(list(baz.values[0]), ["a", "b", "c"])
        self.assertEqual(qux.extent(), 6)
        self.assertEqual(qux.pod(), alembic.Util.POD.kFloat64POD)
        self.assertEqual(qux.values[0], imath.Box3d())
        self.assertEqual(quux.extent(), 9)
        self.assertEqual(quux.pod(), alembic.Util.POD.kFloat64POD)
        self.assertEqual(quux.values[0], imath.M33d())
        self.assertEqual(garply.extent(), 16)
        self.assertEqual(garply.pod(), alembic.Util.POD.kFloat64POD)
        self.assertEqual(garply.values[0], imath.M44d())
        self.assertEqual(waldo.extent(), 1)
        self.assertEqual(waldo.pod(), alembic.Util.POD.kInt32POD)
        self.assertEqual(waldo.values[0], 1)
        self.assertEqual(fred.extent(), 1)
        self.assertEqual(fred.pod(), alembic.Util.POD.kInt32POD)
        self.assertEqual(list(fred.values[0]), [1, 2, 3, 4])
        self.assertEqual(color.extent(), 3)
        self.assertEqual(color.pod(), alembic.Util.POD.kFloat32POD)
        self.assertEqual(color.metadata["interpretation"], "rgb")
        self.assertEqual(color.values[0], imath.Color3f(1, 2, 3))
Ejemplo n.º 16
0
    def test_deep_dict(self):
        filename = os.path.join(TEMPDIR, "cask_deep_dict.abc")

        # read in a simple scene with several shapes
        a = cask.Archive(deep_out())
        t = a.top

        # deep dict access
        self.assertEqual(t.children["A"].name, "A")
        self.assertEqual(t.children["A/B/C/D"].name, "D")
        self.assertEqual(t.children["A"].properties["a"].name, "a")
        self.assertEqual(t.children["A/B/C/D"].properties["a/b/c"].name, "c")
        self.assertRaises(KeyError, t.children.__getitem__, "A/B/C/Z")

        # property accessors
        x = t.children.values()[0]
        self.assertEqual(x.name, "A")
        self.assertEqual(x.properties["a/b/c/myprop"].values[0], "foo")

        # test deep set item on leaf node
        p = t.children["A/B/C/D/meshy"] = cask.PolyMesh()
        self.assertEqual(p.name, "meshy")
        self.assertEqual(p.type(), "PolyMesh")
        self.assertEqual(p.parent, t.children["A/B/C/D"])
        self.assertTrue("meshy" in t.children["A/B/C/D"].children.keys())
        self.assertEqual(len(p.children.keys()), 0)

        # another test
        patch = cask.NuPatch()
        t.children["A/B/C/D/patch"] = patch
        self.assertEqual(patch.name, "patch")
        self.assertEqual(patch.parent, t.children["A/B/C/D"])
        self.assertTrue("patch" in t.children["A/B/C/D"].children.keys())
        self.assertFalse("patch" in t.children.keys())
        self.assertEqual(len(patch.children.keys()), 0)

        # rename test
        patch.name = "nurby"
        self.assertFalse("patch" in t.children["A/B/C/D"].children.keys())
        self.assertTrue("nurby" in t.children["A/B/C/D"].children.keys())
        self.assertEqual(patch.parent, t.children["A/B/C/D"])
        self.assertEqual(t.children["A/B/C/D/nurby"], patch)
        self.assertRaises(KeyError, t.children.__getitem__, "A/B/C/D/patch")

        # test deep dict reassignment
        t.children["A/B/C/D/meshy"] = cask.Xform()
        p2 = t.children["A/B/C/D/meshy"]
        self.assertEqual(p2.name, "meshy")
        self.assertEqual(p2.parent, t.children["A/B/C/D"])
        self.assertFalse(p2.name in t.children.keys())
        self.assertEqual(len(p2.children.values()), 0)
        self.assertEqual(t.children["A/B/C/D/meshy"].type(), "Xform")
        self.assertEqual(p2.type(), "Xform")

        # test deep set item when middle nodes do not exist
        try:
            x = t.children["A/foo/C/D/bar"] = cask.Xform()
            foo = x.properties[".xform/.userProperties/foo"] = cask.Property()
            foo.set_value(1.0)
        except KeyError:
            raise

        # assert that the created nodes are Xforms
        self.assertEqual(t.children["A/foo"].type(), "Xform")
        self.assertEqual(t.children["A/foo/C/D/bar"].type(), "Xform")
        self.assertEqual(foo.type(), "Property")
        self.assertEqual(foo.values[0], 1.0)

        # assert "a" still exists in "A"
        self.assertTrue("a" in t.children["A"].properties.keys())

        # write the archive
        a.write_to_file(filename)

        # re-open and create add'l properties
        a = cask.Archive(filename)
        x = a.top.children["A/foo/C/D/bar"]

        # create new user property
        bar = x.properties[".xform/.userProperties/bar"] = cask.Property()
        bar.set_value(2.0)
        self.assertTrue("bar" in x.properties[".xform/.userProperties"].properties)

        # assert that "foo" was not clobbered when we created "bar"
        self.assertTrue("foo" in x.properties[".xform/.userProperties"].properties)
        foo = x.properties[".xform/.userProperties/foo"]
        self.assertEqual(foo.values[0], 1.0)