Index: /trunk/tests/test_loader.py
===================================================================
--- /trunk/tests/test_loader.py	(revision 20)
+++ /trunk/tests/test_loader.py	(revision 22)
@@ -136,4 +136,9 @@
 """
 
+MUTABLE_KEY = """
+? []
+: []
+"""
+
 class TestDocuments(test_parser.TestDocuments):
 
@@ -181,9 +186,12 @@
 
     def _testFileValues(self, (source, structure)):
-        filename = os.tempnam('/tmp', '_syck_test_')
-        file(filename, 'wb').write(source)
+        tempfile = os.tmpfile()
+        tempfile.write(source)
+        tempfile.seek(0)
         try:
-            self.assertEqualStructure(syck.parse(file(filename)), structure)
-            self.assertEqual(syck.load(file(filename)), structure)
+            self.assertEqualStructure(syck.parse(tempfile), structure)
+            tempfile.seek(0)
+            self.assertEqual(syck.load(tempfile), structure)
+            tempfile.seek(0)
         except:
             os.remove(filename)
@@ -268,7 +276,4 @@
         node = syck.parse(ALIASES)
         values = node.value.values()
-        print values
-        print id(values[0])
-        print id(values[1])
         self.assert_(values[0] is values[1])
 
@@ -277,2 +282,11 @@
         self.assert_(document['foo'] is document['bar'])
 
+class TestMutableKey(unittest.TestCase):
+
+    def testMutableKey(self):
+        document = syck.load(MUTABLE_KEY)
+        self.assertEqual(type(document), list)
+        self.assertEqual(len(document), 1)
+        self.assertEqual(type(document[0]), tuple)
+        self.assertEqual(len(document[0]), 2)
+        self.assertEqual(document[0][0], document[0][1])
Index: /trunk/tests/test_pickle.py
===================================================================
--- /trunk/tests/test_pickle.py	(revision 21)
+++ /trunk/tests/test_pickle.py	(revision 22)
@@ -1,2 +1,3 @@
+# coding: utf-8
 
 import unittest
@@ -252,2 +253,73 @@
             self.assertEqual(left, right)
 
+class MyPrivateType(AnObject):
+    pass
+
+class MyPublicType(AnObject):
+    pass
+
+class MyMapping(AnObject):
+
+    def yaml_construct(cls, node):
+        return cls(**node.value)
+    yaml_construct = classmethod(yaml_construct)
+
+    def yaml_represent(self, node):
+        return syck.Map(self.__dict__.copy(), inline=True)
+
+EXTENSIONS = """
+- !!MyPrivateType [1, 2, 3]
+- !domain.tld,2005/MyPublicType [1, 2, 3]
+- !domain.tld,2005/AnotherPublicType [1, 2, 3]
+- {foo: 1, bar: 2, baz: 3}
+""", [
+    MyPrivateType(1,2,3),
+    MyPublicType(1,2,3),
+    MyPublicType(1,2,3),
+    MyMapping(1,2,3),
+]
+
+class ExLoader(syck.Loader):
+
+    def find_constructor(self, node):
+        if node.kind == 'map':
+            return MyMapping.yaml_construct
+        return super(ExLoader, self).find_constructor(node)
+
+    def make_mapping(self, node):
+        return MyMapping(**node.value)
+
+    def construct_private_MyPrivateType(self, node):
+        return MyPrivateType(*node.value)
+
+    def construct_domain_tld_2005(self, node):
+        return MyPublicType(*node.value)
+
+class ExDumper(syck.Dumper):
+
+    def find_representer(self, object):
+        if isinstance(object, MyMapping):
+            return object.yaml_represent
+        return super(ExDumper, self).find_representer(object)
+
+    def represent_test_pickle_MyPrivateType(self, object):
+        return syck.Seq([object.foo, object.bar, object.baz],
+                tag="x-private:MyPrivateType", inline=True)
+
+    def represent_test_pickle_MyPublicType(self, object):
+        return syck.Seq([object.foo, object.bar, object.baz],
+                tag="tag:domain.tld,2005:APublicType", inline=True)
+
+class TestExtensions(unittest.TestCase):
+
+    def testExtensions(self):
+        source = EXTENSIONS[0]
+        object = EXTENSIONS[1]
+        object2 = syck.load(source, Loader=ExLoader)
+        for left, right in zip(object, object2):
+            self.assertEqual(left, right)
+        source2 = syck.dump(object2, Dumper=ExDumper)
+        object3 = syck.load(source2, Loader=ExLoader)
+        for left, right in zip(object, object3):
+            self.assertEqual(left, right)
+
Index: /trunk/lib/syck/loaders.py
===================================================================
--- /trunk/lib/syck/loaders.py	(revision 21)
+++ /trunk/lib/syck/loaders.py	(revision 22)
@@ -50,8 +50,8 @@
                 value_object = self._convert(node.value[key_node],
                         node_to_object)
-                if key_object in value:
-                    value = None
-                    break
                 try:
+                    if key_object in value:
+                        value = None
+                        break
                     value[key_object] = value_object
                 except TypeError:
@@ -61,5 +61,5 @@
                 value = []
                 for key_node in node.value:
-                    key_object = self_convert(key_node, node_to_object)
+                    key_object = self._convert(key_node, node_to_object)
                     value_object = self._convert(node.value[key_node],
                             node_to_object)
@@ -338,17 +338,17 @@
         return object
 
-def parse(source):
+def parse(source, Loader=Loader, **parameters):
     """Parses 'source' and returns the root of the 'Node' graph."""
-    loader = Loader(source)
+    loader = Loader(source, **parameters)
     return loader.parse()
 
-def load(source):
+def load(source, Loader=Loader, **parameters):
     """Parses 'source' and returns the root object."""
-    loader = Loader(source)
+    loader = Loader(source, **parameters)
     return loader.load()
 
-def parse_documents(source):
+def parse_documents(source, Loader=Loader, **parameters):
     """Iterates over 'source' and yields the root node of each document."""
-    loader = Loader(source)
+    loader = Loader(source, **parameters)
     while True:
         node = loader.parse()
@@ -357,7 +357,7 @@
         yield node
 
-def load_documents(source):
+def load_documents(source, Loader=Loader, **parameters):
     """Iterates over 'source' and yields the root object of each document."""
-    loader = Loader(source)
+    loader = Loader(source, **parameters)
     while True:
         object = loader.load()
Index: /trunk/lib/syck/dumpers.py
===================================================================
--- /trunk/lib/syck/dumpers.py	(revision 21)
+++ /trunk/lib/syck/dumpers.py	(revision 22)
@@ -205,5 +205,5 @@
         return True
 
-def emit(node, output=None, **parameters):
+def emit(node, output=None, Dumper=Dumper, **parameters):
     if output is None:
         dumper = Dumper(StringIO.StringIO(), **parameters)
@@ -214,5 +214,5 @@
         return dumper.output.getvalue()
 
-def dump(object, output=None, **parameters):
+def dump(object, output=None, Dumper=Dumper, **parameters):
     if output is None:
         dumper = Dumper(StringIO.StringIO(), **parameters)
@@ -223,5 +223,5 @@
         return dumper.output.getvalue()
 
-def emit_documents(nodes, output=None, **parameters):
+def emit_documents(nodes, output=None, Dumper=Dumper, **parameters):
     if output is None:
         dumper = Dumper(StringIO.StringIO(), **parameters)
@@ -233,5 +233,5 @@
         return dumper.output.getvalue()
 
-def dump_documents(objects, output=None, **parameters):
+def dump_documents(objects, output=None, Dumper=Dumper, **parameters):
     if output is None:
         dumper = Dumper(StringIO.StringIO(), **parameters)
