import unittest, sys, string
import yaml
from here import flushLeft
import re
import glob
from test import assertEquals, assertError
from yaml.klass import makeClass

try:
   unicode('')
   hasUnicode = 1
except:
   hasUnicode = 0


def loadFlushLeft(stream, typeResolver=None):
    return list(yaml.load(flushLeft(stream), typeResolver))

class YamlTest(unittest.TestCase):

    def runTest(self):
        # reinvent the wheel, instead of trying to 
        # understand unittest's braindead interface
        for name in dir(self.__class__):
            if re.match('test', name):
                exec('self.%s()' % name)

    def verify(self, stream, results):
        self.verifyMany(stream, [results])

    def verifyMany(self, stream, expected):
        results = loadFlushLeft(stream)
        assertEquals(results, expected)

class ClassForRuntime:
    def __init__(self):
        self.foo = 1
        self.bar = 2

class YamlLoader:
    # XXX python 2.1 has weak lambda support
    def __init__(self, doc):
        self.doc = doc
    def __call__(self):
        return list(yaml.load(self.doc['yaml']))

class TestFromSpec(YamlTest):
    def testFromYaml(self):
        testFiles = glob.glob('TestingSuite/*.yml')
        for file in testFiles:
            # print "\n\n\n\n", file
            try:
                docs = yaml.loadFile(file)
            except IOError:
                raise "See TESTING for how to set up TestingSuite"
            for doc in docs:
                if doc.has_key('python'):
                    self.verifyOneDoc(doc)
                if doc.has_key('error') and doc['error'].has_key('python'):
                    assertError(YamlLoader(doc), doc['error']['python'])

    def verifyOneDoc(self, doc):
        if doc.has_key('python_setup'):
            exec(doc['python_setup'])
        data = eval(doc['python'])
        # print data
        assertEquals(list(yaml.load(doc['yaml'])), data)
        if not doc.has_key('NO_ROUND_TRIP'):
            self.assertRoundTrip(data)

    def assertRoundTrip(self, data):
        # XXX - A5 won't round trip when enclosed by 
        # an array...need to investigate
        for item in data:
            # print dump(item)
            assertEquals(item, 
                yaml.load(yaml.dump(item)).next(), 'roundtrip')


class TestUtils(YamlTest):    
    class Dummy:
        pass

    def testMakeClass(self):
        self.assertEquals(42,
            makeClass('YamlTest', 'TestUtils.Dummy', 
                {'a': 27, 'b': 42}).b)

    class FromYaml:
        def from_yaml(self, dict):
            self.sum = dict['a'] + dict['b']
            return self

    def testMakeClassFromYaml(self):
        self.assertEquals(6,
            makeClass('YamlTest', 'TestUtils.FromYaml',
                {'a': 2, 'b': 4}).sum)


def testVersion():
    from yaml import __version__
    assertEquals(__version__, str(yaml.loadFile('CHANGELOG').next()[0]['version']))

if __name__ == '__main__':
    import TestYamlBasics
    import TestNestedText
    import TestInlineTokenizer
    import TestDumper
    ts = unittest.TestSuite()
    ts.addTest(TestYamlBasics.Test())
    ts.addTest(TestNestedText.Test())
    ts.addTest(TestInlineTokenizer.Test())
    ts.addTest(TestDumper.Test())
    ts.addTest(TestFromSpec())
    ts.addTest(TestUtils())
    unittest.TextTestRunner().run(ts)
    yaml.dumpToFile(sys.stdout, {'TESTING dumpToFile': 'ok'})
    testVersion()
