コード例 #1
0
 def raw_input(self, prompt='Input:'):
     if not isinstance(prompt, str):
         prompt = str(prompt)
     self.input_event = ManualResetEvent(False)
     self.setup_input_box(prompt)
     self.input_event.WaitOne()
     self.remove_input_box()
     return self._raw_input_text
コード例 #2
0
    def __init__(self, printer, context, root):
        self._input_data = []
        self.original_context = context
        self.printer = printer
        self.prompt = root.prompt
        self.root = root
        self.done_first_run = False
        self._sync = ManualResetEvent(False)
        self.ff3 = False

        self.FontSize = 15
        self.Margin = Thickness(0)
        self.FontFamily = FontFamily(
            "Consolas, Monaco, Lucida Console, Global Monospace")
        self.AcceptsReturn = True
        self.BorderThickness = Thickness(0)
        self.VerticalScrollBarVisibility = ScrollBarVisibility.Auto
        self.MinWidth = 300

        def reset():
            "Clear the console, its history and the execution context."
            self._reset_needed = True
            return 'resetting'

        def input(prompt='Input:'):
            'input([prompt]) -> value\n\nEquivalent to eval(raw_input(prompt)).'
            return eval(self.context['raw_input'](prompt), self.context,
                        self.context)

        self.original_context['reset'] = reset
        self.original_context['gohome'] = gohome
        self.original_context['exit'] = 'There is no escape...'
        self.original_context['raw_input'] = self.raw_input
        self.original_context['input'] = input

        # for debugging only!
        self.original_context['root'] = root

        self.context = {}
        self.history = None
        self._reset_needed = False
        self._thread = None
        self._thread_reset = None
        self._raw_input_text = ''
        self._temp_context = None
        self.engine = Python.CreateEngine()
        self.scope = self.engine.CreateScope()

        self._original_caret = None
        if hasattr(self, 'CaretBrush'):
            self._original_caret = self.CaretBrush
        self._disabled = SolidColorBrush(Colors.White)

        self.KeyDown += self.handle_key
        self.TextChanged += self.text_changed
コード例 #3
0
    def execute(self, contents):
        self.printer.print_lines(contents)
        self.Text = ''
        self.history.append(contents)

        self._sync.Reset()
        started = ManualResetEvent(False)
        if self._temp_context is not None:
            self.context.update(self._temp_context)

        def _execute():
            context = self.context
            started.Set()
            try:
                code = compile(contents + '\n', '<stdin>', 'single',
                               PyCF_DONT_IMPLY_DEDENT)
                exec code in context
            except:
                if reset_event.WaitOne(1):
                    # don't print exception messages if thread has been terminated
                    return
                exc_type, value, tb = sys.exc_info()
                if value is None:
                    # String exceptions
                    # workaround for IronPython bug
                    exc_type = Exception
                    value = Exception('StringException')

                tblist = traceback.extract_tb(tb)
                message = traceback.format_list(tblist)
                del message[:1]
                if message:
                    # we don't print the 'Traceback...' part for SyntaxError
                    message.insert(0, "Traceback (most recent call last):\n")
                message.extend(traceback.format_exception_only(
                    exc_type, value))
                self.printer.print_new(''.join(message))

            # access through closure not on self as we may be an orphaned
            # thread - with a new reset_event on self
            result = reset_event.WaitOne(0)
            if not reset_event.WaitOne(0):
                self.completed()
            self._sync.Set()

        self._thread_reset = reset_event = ManualResetEvent(False)
        self._thread = Thread(ThreadStart(_execute))
        self._thread.IsBackground = True
        self._thread.Name = "executing"
        self._thread.Start()
        self.prompt.Visibility = Visibility.Collapsed
        if hasattr(self, 'CaretBrush'):
            self.CaretBrush = self._disabled
        started.WaitOne()
コード例 #4
0
    def do_synchronously(self, function, wait_sync=False):
        event = ManualResetEvent(False)

        def do_operation():
            function()
            event.Set()

        self.Dispatcher.BeginInvoke(do_operation)
        event.WaitOne()
        if wait_sync:
            # wait for execution to complete
            self._sync.WaitOne()
コード例 #5
0
from System import Uri, AsyncCallback
from System.IO import StreamReader
from System.Net import WebRequest
from System.Windows.Browser import HtmlPage
import time
import unittest

from System.Windows.Threading import Dispatcher
from System.Threading import ManualResetEvent, Thread, ThreadStart
are = ManualResetEvent(False)

TEST_NET_CONTENT = '[[[CONTENT OF TEST_NET.TXT]]]'


def puts(*a):
    print(a)


def web_request(obj, uri_string, func):
    req = WebRequest.Create(Uri(uri_string))
    req.BeginGetResponse(AsyncCallback(web_complete(obj, func)), req)


def web_complete(obj, func):
    def __web_complete(a):
        req = a.AsyncState
        res = req.EndGetResponse(a)
        content = StreamReader(res.GetResponseStream()).ReadToEnd()
        func(content)
        are.Set()
コード例 #6
0
class ConsoleTextBox(TextBox):
    def __new__(cls, printer, context, root):
        return TextBox.__new__(cls)

    def __init__(self, printer, context, root):
        self._input_data = []
        self.original_context = context
        self.printer = printer
        self.prompt = root.prompt
        self.root = root
        self.done_first_run = False
        self._sync = ManualResetEvent(False)
        self.ff3 = False

        self.FontSize = 15
        self.Margin = Thickness(0)
        self.FontFamily = FontFamily(
            "Consolas, Monaco, Lucida Console, Global Monospace")
        self.AcceptsReturn = True
        self.BorderThickness = Thickness(0)
        self.VerticalScrollBarVisibility = ScrollBarVisibility.Auto
        self.MinWidth = 300

        def reset():
            "Clear the console, its history and the execution context."
            self._reset_needed = True
            return 'resetting'

        def input(prompt='Input:'):
            'input([prompt]) -> value\n\nEquivalent to eval(raw_input(prompt)).'
            return eval(self.context['raw_input'](prompt), self.context,
                        self.context)

        self.original_context['reset'] = reset
        self.original_context['gohome'] = gohome
        self.original_context['exit'] = 'There is no escape...'
        self.original_context['raw_input'] = self.raw_input
        self.original_context['input'] = input

        # for debugging only!
        self.original_context['root'] = root

        self.context = {}
        self.history = None
        self._reset_needed = False
        self._thread = None
        self._thread_reset = None
        self._raw_input_text = ''
        self._temp_context = None
        self.engine = Python.CreateEngine()
        self.scope = self.engine.CreateScope()

        self._original_caret = None
        if hasattr(self, 'CaretBrush'):
            self._original_caret = self.CaretBrush
        self._disabled = SolidColorBrush(Colors.White)

        self.KeyDown += self.handle_key
        self.TextChanged += self.text_changed

    def reset(self):
        sys.ps1 = ps1
        sys.ps2 = ps2
        self.printer.clear()
        self._reset_needed = False
        self.context.clear()
        self.context = self.original_context.copy()
        self.history = ConsoleHistory()
        self.printer.print_new(banner)
        if not self.done_first_run:
            self.done_first_run = True
            self.browser_sniff()

    def browser_sniff(self):
        useragent = HtmlPage.BrowserInformation.UserAgent
        match = re.search(FF3_RE, useragent)
        if match is not None:
            browser = match.groups()[0]
            self.printer.print_new(FF3_MESSAGE % browser)
            self.ff3 = True

    def OnKeyDown(self, event):
        # needed so that we get KeyDown
        # for del and backspace events etc
        pass

    def text_changed(self, sender, event):
        # replace any tabs that are pasted in
        if '\t' in self.Text:
            self.Text = self.Text.replace('\t', '    ')
            self.SelectionStart = len(self.Text)

    def write(self, data):
        self.printer.write(data)

    def is_complete(self, text, pos):
        if len(text.splitlines()) > 1 and pos < len(text.rstrip()):
            return False
        if text.endswith('\\'):
            return False

        source = self.engine.CreateScriptSourceFromString(
            text, 'stdin', SourceCodeKind.InteractiveCode)

        try:
            result = source.GetCodeProperties()
        except TypeError:
            # happens when text is 'lambda' for some reason
            return True

        if result == ScriptCodeParseResult.IncompleteToken:
            return False
        elif result == ScriptCodeParseResult.IncompleteStatement:
            if not text.rstrip(' ').endswith('\n'):
                return False
        return True

    def on_first_line(self, text):
        first_line_end = text.find('\n')
        if first_line_end == -1:
            return True
        return self.SelectionStart <= first_line_end

    def on_last_line(self, text):
        last_line_end = text.rfind('\n')
        if last_line_end == -1:
            return True
        return self.SelectionStart > last_line_end

    def handle_key(self, sender, event):
        # Mac Safari uses '\r' for newlines in Silverlight TextBox??
        contents = self.Text.replace('\r\n', '\n').replace('\r', '\n')
        key = event.Key
        start = self.SelectionStart
        end = start + self.SelectionLength

        modifiers = Keyboard.Modifiers
        control = (modifiers & ModifierKeys.Control) or (modifiers
                                                         & ModifierKeys.Apple)
        if key == Key.C and control:
            event.Handled = True
            self.keyboard_interrupt()
            return

        if self._thread is not None:
            # ignore key events (we have already checked for Ctrl-C)
            event.Handled = True
            return

        if key != Key.Enter:
            if key == Key.Up:
                if self.on_first_line(contents):
                    event.Handled = True
                    previous = self.history.back(contents)
                    if previous is not None:
                        self.Text = previous
                        self.SelectionStart = len(previous)
                    return

            elif key == Key.Down:
                if self.on_last_line(contents):
                    event.Handled = True
                    next = self.history.forward(contents)
                    if next is not None:
                        self.Text = next
                        self.SelectionStart = len(next)
                    return

            elif key == Key.Tab:
                event.Handled = True
                self.Text = self.Text[:start] + '    ' + self.Text[end:]
                self.SelectionStart = start + 4
                return

            if key == key.Add and self.ff3:
                if not (modifiers & ModifierKeys.Shift):
                    event.Handled = True
                    self.Text = self.Text[:start] + '=' + self.Text[end:]
                    self.SelectionStart = start + 1
                    return

            TextBox.OnKeyDown(self, event)
            return

        event.Handled = True
        if empty_or_comment_only(contents):
            # needed or we get a SyntaxError
            self.Text = ''
            self.printer.print_lines(contents)
            self.printer.scroll()
            return

        # manual handling unfortunately
        # means things like trailing comments break
        # these functions; so not ideal
        stripped = contents.rstrip()
        if stripped == 'gohome':
            gohome()
        elif stripped == 'reset':
            contents = 'reset()'
        elif stripped == 'import this':
            # import hook so that importing *worked*
            # would be a better solution...
            self.printer.print_lines(stripped)
            self.Text = ''
            self.history.append(contents)
            import this
            self.context['this'] = this
            self.printer.set_prompt()
            self.printer.scroll()
            return

        if not self.is_complete(contents, start):
            self.do_indent(start)
        else:
            self.execute(contents)

    def execute(self, contents):
        self.printer.print_lines(contents)
        self.Text = ''
        self.history.append(contents)

        self._sync.Reset()
        started = ManualResetEvent(False)
        if self._temp_context is not None:
            self.context.update(self._temp_context)

        def _execute():
            context = self.context
            started.Set()
            try:
                code = compile(contents + '\n', '<stdin>', 'single',
                               PyCF_DONT_IMPLY_DEDENT)
                exec code in context
            except:
                if reset_event.WaitOne(1):
                    # don't print exception messages if thread has been terminated
                    return
                exc_type, value, tb = sys.exc_info()
                if value is None:
                    # String exceptions
                    # workaround for IronPython bug
                    exc_type = Exception
                    value = Exception('StringException')

                tblist = traceback.extract_tb(tb)
                message = traceback.format_list(tblist)
                del message[:1]
                if message:
                    # we don't print the 'Traceback...' part for SyntaxError
                    message.insert(0, "Traceback (most recent call last):\n")
                message.extend(traceback.format_exception_only(
                    exc_type, value))
                self.printer.print_new(''.join(message))

            # access through closure not on self as we may be an orphaned
            # thread - with a new reset_event on self
            result = reset_event.WaitOne(0)
            if not reset_event.WaitOne(0):
                self.completed()
            self._sync.Set()

        self._thread_reset = reset_event = ManualResetEvent(False)
        self._thread = Thread(ThreadStart(_execute))
        self._thread.IsBackground = True
        self._thread.Name = "executing"
        self._thread.Start()
        self.prompt.Visibility = Visibility.Collapsed
        if hasattr(self, 'CaretBrush'):
            self.CaretBrush = self._disabled
        started.WaitOne()

    @invoke
    def completed(self, reset_temp=True):
        if reset_temp:
            self._temp_context = None
        self._thread = None
        self.prompt.Visibility = Visibility.Visible
        self._thread_reset = None
        if hasattr(self, 'CaretBrush'):
            self.CaretBrush = self._original_caret
        if self._reset_needed:
            self.reset()
        else:
            self.printer.set_prompt()
            self.printer.scroll()

    def do_indent(self, start):
        to_the_left = self.Text[:start + 1]
        lines = to_the_left.splitlines()
        initial_indent = '    '
        for line in lines:
            # we do this incase the user is using one or two space
            # indent instead of four
            if line.startswith(' '):
                initial_indent = get_indent(line)
                break

        # there *must* be something here because an empty textbox
        # would already have been caught by empty_or_comment_only
        last_line = lines[-1]
        new_indent = current_indent = get_indent(last_line)
        if last_line.rstrip().endswith(':'):
            new_indent = current_indent + initial_indent
        elif is_terminator(last_line):
            new_indent = ' ' * (len(current_indent) - len(initial_indent))

        new_start = self.SelectionStart
        new_pos = new_start + len(new_indent)
        self.Text = self.Text[:new_start] + '\n' + new_indent + self.Text[
            new_start:]
        self.SelectionStart = new_pos + 1

    def keyboard_interrupt(self):
        # Aborting threads doesn't work on Silverlight :-(
        #self._thread.Abort()
        reset_temp = True
        if self._thread_reset is not None:
            reset_temp = False
            # signal to background thread not to complete
            self._thread_reset.Set()
            context = self.context
            self._temp_context = context.copy()
            # This will hopefully cause the existing thread to error out
            context.clear()
            context['raw_input'] = context['input'] = blow_up

        self._thread_reset = None
        self._thread = None

        if self.Text.strip():
            self.history.append(self.Text)
        self.printer.print_new('KeyboardInterrupt')
        self.Text = ''
        self.completed(reset_temp)

    @invoke
    def setup_input_box(self, prompt):
        self.Visibility = Visibility.Collapsed
        self.root.rawInputPrompt.Text = prompt + ' '
        self.root.rawInputField.Text = ''
        self.root.rawInputField.Width = self.Width - 60
        self.root.rawInput.Visibility = Visibility.Visible
        self.root.rawInputField.KeyDown += self.check_for_enter
        self.root.rawInputField.Focus()

    @invoke
    def remove_input_box(self):
        self.Visibility = Visibility.Visible
        self.root.rawInput.Visibility = Visibility.Collapsed
        self.root.rawInputField.KeyDown -= self.check_for_enter
        self.printer.print_new(self.root.rawInputPrompt.Text +
                               self._raw_input_text)
        self.Focus()

    def check_for_enter(self, sender, event):
        if event.Key == Key.Enter:
            event.Handled = True
            self._raw_input_text = self.root.rawInputField.Text
            self.input_event.Set()

    def raw_input(self, prompt='Input:'):
        if not isinstance(prompt, str):
            prompt = str(prompt)
        self.input_event = ManualResetEvent(False)
        self.setup_input_box(prompt)
        self.input_event.WaitOne()
        self.remove_input_box()
        return self._raw_input_text

    def _handle_lines(self, lines):
        try:
            self._input_data = []
            for line in lines:
                self.handle_line(line)

            if self._input_data:
                self.handle_line('')
            self.Dispatcher.BeginInvoke(lambda: self.Focus())
        except Exception, e:
            _debug('Handle lines', e)
コード例 #7
0
    def test_all(self):
        from System.Threading import ManualResetEvent, Thread, ThreadStart

        class MyOC:
            one = 'one'
            two = 'two'
            three = 'three'
            four = 'four'
            five = 'five'
            six = 'six'

        class MyUserType(object):
            one = 'one'
            two = 'two'
            three = 'three'
            four = 'four'
            five = 'five'
            six = 'six'

        class BaseUserTypeOne(object):
            pass

        class BaseUserTypeTwo(object):
            pass

        class DerivedUserType(BaseUserTypeOne):
            pass

        go = ManualResetEvent(False)

        # setup a table used for transforming loop iterations into identifiers.
        # 1 becomes A, 11 becomes AA, 12 becomes AB, 123 becomes ABC, etc...

        identityTable = [chr(x) for x in range(256)]
        transTable = ''
        for x in identityTable:
            if ord(x) >= ord('0') and ord(x) <= ord('9'):
                transTable = transTable + chr(ord('A') + ord(x) - ord('0'))
            else:
                transTable = transTable + x

        # base test infrastructure, reader thread, writer thread, and test
        # runner
        def reader():
            try:
                try:
                    go.WaitOne()
                    for i in xrange(loopCnt):
                        readerWorker(i)
                except Exception, e:
                    self.fail(
                        'Test failed, unexpected exception from reader: %r' %
                        e)
            finally:
                global readerAlive
                readerAlive = False

        class writer:
            def __init__(self, writer, index):
                self.writer = writer
                self.index = index

            def __call__(self, *args):
                try:
                    try:
                        go.WaitOne()
                        for i in xrange(loopCnt):
                            self.writer(i, self.index)
                    except Exception, e:
                        self.fail(
                            'Test failed (writer through exception): %r' % e)
                finally:
                    global writerAlive
                    writerAlive = False

        def runTest():
            global writerAlive
            global readerAlive
            writerAlive = True
            readerAlive = True

            a = Thread(ThreadStart(reader))
            a.IsBackground = True
            a.Start()

            if isinstance(writerWorker, tuple):
                b = []
                index = 0
                for wr in writerWorker:
                    th = Thread(ThreadStart(writer(wr, index)))
                    th.IsBackground = True
                    th.Start()
                    b.append(th)
                    index = index + 1
            else:
                b = [Thread(ThreadStart(writer(writerWorker, 0)))]
                b[0].IsBackground = True
                b[0].Start()

            go.Set()

            a.Join()
            for th in b:
                th.Join()

        # individual test cases, setup reader/writer workers
        # and then call run test

        # OldClass test cases

        def Reader_Dir(i):
            x = dir(oc)

        def Reader_CheckOneKey(i):
            self.assertEqual(getattr(oc, 'outsideFuncEnv'),
                             outsideFuncEnvValue)

        def Reader_HasAttr(i):
            attrName = str(i).translate(transTable)
            hasattr(oc, attrName)

        def Reader_VerifyAllPresent(i):
            # verify that we can find all the previous values in the dictionary
            global writerAlive
            if not writerAlive:
                return  # writer takes signifcantly less time, stop checking once we're no longer experiencing contention

            global prevValues
            for x in prevValues.keys():
                #print 'checking ', x
                self.assertEqual(hasattr(oc, x), True)
                #print getattr(oc,x), prevValues[x]
                self.assertEqual(getattr(oc, x), prevValues[x])
            for x in dir(oc):
                if not prevValues.has_key(x):
                    prevValues[x] = getattr(oc, x)

        # generic writer, just keeps adding more and more attributes
        def Writer_Generic(i, writerIndex):
            attrName = str(i).translate(transTable)
            x = object()
            setattr(oc, attrName, x)
            self.assertEqual(getattr(oc, attrName), x)

        # generic writer, adds  an attribute and then removes it.
        def Writer_Generic_Delete(i, writerIndex):
            attrName = str(i).translate(transTable)
            x = object()
            setattr(oc, attrName, x)
            self.assertEqual(getattr(oc, attrName), x)
            delattr(oc, attrName)

        # adds attributes to the class, deletes them in batches of 50
        def Writer_Generic_BatchDelete(i, writerIndex):
            attrName = str(i).translate(transTable)
            x = object()
            setattr(oc, attrName, x)
            self.assertEqual(getattr(oc, attrName), x)
            if i != 0 and i % 50 == 0:
                for x in xrange(i - 50, i):
                    attrName = str(x).translate(transTable)
                    delattr(oc, attrName)

        def Reader_ExtraKeys(i):
            global oc
            if (i % 6) == 0:
                # create a new instance every 6 iterations (6 is the number
                # of custom keys per old-instance dict)
                oc = MyOC()
            if hasattr(oc, 'abc'): self.assertEqual(oc.abc, 'abc')
            if hasattr(oc, 'abcd'): self.assertEqual(oc.abcd, 'abcd')
            if hasattr(oc, 'abcde'): self.assertEqual(oc.abcde, 'abcde')
            if hasattr(oc, 'abcdef'): self.assertEqual(oc.abcdef, 'abcdef')
            if hasattr(oc, 'abcdefg'): self.assertEqual(oc.abcdefg, 'abcdefg')
            if hasattr(oc, 'abcdefgh'):
                self.assertEqual(oc.abcdefgh, 'abcdefgh')

        def Writer_ExtraKeys(i, writerIndex):
            if i % 6 == 0: oc.abc = 'abc'
            elif i % 6 == 1: oc.abcd = 'abcd'
            elif i % 6 == 2: oc.abcde = 'abcde'
            elif i % 6 == 3: oc.abcdef = 'abcdef'
            elif i % 6 == 4: oc.abcdefg = 'abcdefg'
            elif i % 6 == 5: oc.abcdefgh = 'abcdefgh'

        def Init_OldClass(loopCnt):
            global oc, outsideFuncEnvValue, prevValues
            prevValues = {}

            outsideFuncEnvValue = object()
            oc = MyOC()

            # fill in some attributes so we don't hit extra values...
            for id in range(loopCnt, loopCnt + 20):
                setattr(oc, str(id).translate(transTable), object())

            # now set a value that's outside of the extra values
            setattr(oc, 'outsideFuncEnv', outsideFuncEnvValue)

        def Nop(i):
            pass

        # List Test Cases

        def List_Writer(i, writerIndex):
            myList.append(i)

        def List_Writer_Extend(i, writerIndex):
            myList.extend([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

        def List_Reader(i):
            global lastRead
            if myList: lastRead = myList[-1]

        def List_Clear(i, writerIndex):
            if i % 50 == 0:
                if myList: del myList[:]

        def List_Slice_Set(i, writerIndex):
            if i % 50 == 0:
                myList[:] = []

        def List_Index_Writer(i, writerIndex):
            global lastRead
            if myList: myList[-1] = lastRead

        def Init_List_Sort(loopCnt):
            global listOfLists1, listOfLists2

            listOfLists1 = []
            listOfLists2 = []
            for x in range(200):
                listOfLists1.append([])
                listOfLists2.append([])
            for x in listOfLists1:
                for y in listOfLists2:
                    x.append(y)
                    y.append(x)

        def List_Sorter(i, writerIndex):
            global listOfLists1, listOfLists2
            if writerIndex == 1: listOfLists1.sort()
            else: listOfLists2.sort()

        def Init_List(loopCnt):
            global myList, lastRead
            myList = []
            lastRead = 0

        def PostCondition_List(expectedLength):
            # create a closer around the inner function w/ the expected length
            def PostCondition_List_Inner():
                self.assertEqual(len(myList), expectedLength)

            return PostCondition_List_Inner

        # user type test cases

        # verify mro / base classes update atomically
        def UserType_Write_Bases(i, writerIndex):
            if BaseUserTypeOne in myUserType.__bases__:
                myUserType.__bases__ = (BaseUserTypeTwo, )
            else:
                myUserType.__bases__ = (BaseUserTypeOne, )

        def UserType_Read_BasesAndMro(i):
            bases = myUserType.__bases__
            self.assertTrue(bases == (BaseUserTypeOne, )
                            or bases == (BaseUserTypeTwo, ))
            mro = myUserType.__mro__
            self.assertTrue(
                mro == (DerivedUserType, BaseUserTypeOne, object)
                or mro == (DerivedUserType, BaseUserTypeTwo, object))

        def Init_UserType_Bases(loopCnt):
            global myUserType
            myUserType = DerivedUserType

        def Init_UserType(loopCnt):
            global oc, outsideFuncEnvValue, prevValues
            prevValues = {}

            outsideFuncEnvValue = object()
            oc = MyUserType()

            # set a value that's outside of the extra values
            setattr(oc, 'outsideFuncEnv', outsideFuncEnvValue)

        def Init_NewTypeMaker(loopCnt):
            global baseTypes
            baseTypes = (object, )

        def CreateType(i, writerIndex):
            global baseTypes

            # we keep deriving a new type from a new combination of base types - always
            # object and an ever-growing list of old-style classes.  Thread 0 is responsible
            # for pushing a new base type in.  This causes all the creation threads to hit
            # contention and wait for a type to be published.
            type('foo', baseTypes, {})

            if writerIndex == 0:

                class foo:
                    pass

                baseTypes = baseTypes + (foo, )

        testCases = [  # initialization, reader, writer, test loopCnt, post-condition.
            #    Multiple writes can be provided w/ a tuple

            # new type maker tests
            (Init_NewTypeMaker, Nop, (CreateType, CreateType, CreateType,
                                      CreateType, CreateType, CreateType), 100
             ),

            # user type tests
            (Init_UserType, Reader_ExtraKeys, (Writer_ExtraKeys,
                                               Writer_ExtraKeys), 100000),
            (Init_UserType, Reader_CheckOneKey, Writer_Generic_BatchDelete,
             10000),
            (Init_UserType, Reader_CheckOneKey, Writer_Generic, 10000),
            (Init_UserType, Reader_CheckOneKey, Writer_Generic_Delete, 10000),
            (Init_UserType, Reader_Dir, Writer_Generic_BatchDelete, 10000),
            (Init_UserType, Reader_VerifyAllPresent, Writer_Generic, 10000),
            (Init_UserType, Reader_Dir, Writer_Generic_Delete, 10000),
            (Init_UserType, Reader_HasAttr, Writer_Generic, 10000),
            (Init_UserType_Bases, UserType_Read_BasesAndMro,
             UserType_Write_Bases, 10000),

            # list tests
            (Init_List_Sort, Nop, (List_Sorter, List_Sorter), 1000),
            (Init_List, List_Reader, (List_Index_Writer, List_Slice_Set),
             100000),
            (Init_List, List_Reader, (List_Index_Writer, List_Clear), 100000),
            (Init_List, List_Reader, (List_Writer), 10000,
             PostCondition_List(10000)),
            (Init_List, List_Reader, (List_Index_Writer, List_Writer_Extend),
             10000, PostCondition_List(10000 * 10)),
            (Init_List, List_Reader, (List_Writer, List_Index_Writer), 10000,
             PostCondition_List(10000)),
            (Init_List, Nop, (List_Writer_Extend, List_Writer_Extend), 10000,
             PostCondition_List(10000 * 2 * 10)),
            (Init_List, Nop, (List_Writer, List_Writer, List_Writer), 10000,
             PostCondition_List(10000 * 3)),

            # old-style class tests
            (Init_OldClass, Reader_ExtraKeys, (Writer_ExtraKeys,
                                               Writer_ExtraKeys), 100000),
            (Init_OldClass, Reader_CheckOneKey, Writer_Generic_BatchDelete,
             10000),
            (Init_OldClass, Reader_CheckOneKey, Writer_Generic, 10000),
            (Init_OldClass, Reader_CheckOneKey, Writer_Generic_Delete, 10000),
            (Init_OldClass, Reader_Dir, Writer_Generic_BatchDelete, 10000),
            (Init_OldClass, Reader_VerifyAllPresent, Writer_Generic, 10000),
            (Init_OldClass, Reader_Dir, Writer_Generic_Delete, 10000),
            (Init_OldClass, Reader_HasAttr, Writer_Generic, 10000),
        ]

        def doOneTest(test):
            """runs a single test, argument is a testCase tuple"""
            print 'running test', test
            global loopCnt, writerWorker, readerWorker

            # call init function
            loopCnt = test[3]
            test[0](loopCnt)

            # set our workers
            readerWorker = test[1]
            writerWorker = test[2]

            # set our loopcnt

            # run the test
            runTest()

            if len(test) >= 5: test[4]()

        for test in testCases:
            doOneTest(test)