As usual, the scene graph in Spineless is actually a tree of nodes (though some scene graphs are acyclic graphs, this would prevent a lot of optimizations at least with my approach). There are basically two approaches to implementing interesting behaviour in a scene graph: inheriting and composition.
Inheriting means you have a base Node class from which you inherit special node classes, such as LightNode, CameraNode and ModelNode. This is often the first approach you'd think of, and very early incarnations of Spineless used this approach. The problem with this approach is that inheritance is a static relationship: you can't (at least easily, though I'm sure this would be possible with some metaclass hackery) change the superclass of a class at runtime. If you can't comprehend what this means, let me give an example:
Let's assume you have a basic CameraNode which you can position around the world, and which allows you to render the world from its viewpoint. Now, you realize you need a camera which can track objects by always rotating to look at them. No problem, you just inherit from CameraNode and write a TrackingCameraNode. For some other situation, you need a camera that can follow another node, such as a character. Again, no problem, you'll just create a FollowingCameraNode inheriting from CameraNode. And then you need a camera that can follow a node while tracking another node... No problem, just inherit from both FollowingCameraNode and TrackingCameraNode, creating a FollowingTrackingCameraNode? Welcome the dreaded Diamond of Inheritance. Both of them inherit from CameraNode, so you are inheriting from it twice, and everyone knows this is a Bad Thing. Not to mention it's really ugly having to create new subclasses just to implement new functionality.
Now, using composition, this would be much cleaner. One way of handling the above camera problem would be having a CameraNode, a FollowerNode and a TrackerNode. Now, TrackerNode would be the parent of CameraNode, and FollowerNode would be a parent of TrackerNode, like this: root -> follower -> tracker -> camera. Now you can dynamically make any type of node a follower, a tracker or a combination of these. You connect nodes together to create new functionality, not write new classes.
The Spineless scene graph doesn't stop here though. In Spineless, there are no subclasses of Node whatsoever, and nodes are just dumb containers for arbitraty attributes: they have no idea about what their attributes are for. Contrary to most scene graphs, even the transformation of a node is no special attribute. All the intelligence is contained in the World class and various "workers" for different subsystems, such as renderer, audio and physics. From the developer's point of view, all you have to do is create nodes, assign their attributes and connect them to each other. Then assign the root of your tree as the root node of a World. Something like this:
rootNode = Node()
rootNode.projection = PerspectiveProjection(45.0, 1.0, 100.0)
rootNode.lighting = Lighting(enable=True)
lightNode = Node(rootNode)
lightNode.light = DirectionalLight()
lightNode.rotation = quaternion.lookAt(Vector(0, -1, 0))
tinyBox = Box(0.1, 0.1, 0.1)
boxNode = Node(rootNode)
boxNode.render = tinyBox.createPrimitive().render
boxNode.renderMaterial = Material()
boxNode.renderMaterial.diffuse = color.RED
boxNode.collisionGeometry = tinyBox.createCollisionGeometry()
cameraNode = Node(rootNode)
cameraNode.position = Vector(0, 5, 5)
myWorld = World()
myWorld.rootNode = rootNode
myView = View()
myView.viewNode = cameraNode
Now for example, the projection and lighting attributes are recognized by the renderer (inside the view) and collisionGeometry is recognized by the Space class, which keeps track of spatial relationships between nodes: collisions, sorting nodes by distance etc. You'll probably notice that all of this is quite low level. Also, details of the interface are not yet set in the stone, especially concerning geometry. I'm yet to create a higher level interface, but I already have a plan for it. The plan is called entities.
Entities manage subtrees of nodes: they always have a rootNode, and might have other named nodes. For example, a third person camera entity might have a focusNode which you can attach to a node you want to follow and a viewNode which is the actual camera location. A ModelNode might contain a list of meshNodes and helperNodes. These are of course implemented using the low-level nodes. Also, they will usually be loaded from data files instead of being specified manually.
Whew, that was a long post. I hope I get at least one useful comment for this. :) Constructive criticism and questions are very welcome. I'm probably going to explain the inner workings of scene management in a later post, especially if there's interest (which you can express by commenting).
EDIT: Before anyone comments on a tree structure not being the best option for all purposes: that's just the public interface visible for the developer. Internally, nodes are stored in various data structures best suited for each task. But more on this in a later post.