예제 #1
0
def test_executor():
    """ Test the executor """
    ex = Executor()
    ex2 = Executor()
    assert ex is ex2

    ex3 = pickle.loads(pickle.dumps(ex))

    assert ex3 is ex

    assert len(_executor_cache) == 1

    assert ex.impl.submit(lambda x: x * 2, 4).result() == 8
    ex.shutdown(wait=True)
    ex3.shutdown(wait=False)

    # Executor should be shutdown at this point
    with pytest.raises(RuntimeError):
        ex2.impl.submit(lambda x: x * 2, 4)

    assert len(_executor_cache) == 1

    # Force collection
    del ex, ex2, ex3

    # Check that callbacks
    assert len(_executor_cache) == 0
예제 #2
0
    def __init__(self, factory, *args, **kwargs):
        """
        Parameters
        ----------
        factory : callable
            Function which creates the CASA table
        *args : tuple
            Positional arguments passed to factory.
        **kwargs : dict
            Keyword arguments passed to factory.
        __executor_key__ : str, optional
            Executor key. Identifies a unique threadpool
            in which table operations will be performed.
        """

        # Save the arguments as keys for pickling and tokenising
        self._factory = factory
        self._args = args
        self._kwargs = kwargs

        # NOTE(sjperkins)
        # Copy the kwargs and remove (any) __executor_key__
        # This is smelly but we do this to maintain
        # key uniqueness derived from
        # the *args and **kwargs in the MetaClass
        # as well as uniqueness when pickling/unpickling
        # A named keyword is possible but
        # TableProxy(*args, *kwargs)
        # doesn't produce the same unique key as
        # TableProxy(*args, ex_key=..., **kwargs)
        kwargs = kwargs.copy()
        self._ex_key = kwargs.pop("__executor_key__", STANDARD_EXECUTOR)

        # Store a reference to the Executor wrapper class
        # so that the Executor is retained while this TableProxy
        # still lives
        self._ex_wrapper = ex = Executor(key=self._ex_key)
        self._table_future = table = ex.impl.submit(factory, *args, **kwargs)

        weakref.finalize(self, _table_future_finaliser, ex, table, args,
                         kwargs)

        # Reference to the internal ThreadPoolExecutor
        self._ex = ex.impl

        # Private, should be inaccessible
        self._write = False
        self._writeable = ex.impl.submit(_iswriteable, table).result()

        should_be_writeable = not kwargs.get('readonly', True)

        if self._writeable is False and should_be_writeable:
            # NOTE(sjperkins)
            # This seems to happen if you've opened a WSRT.MS with
            # readonly=False, and then you try to open WSRT.MS::SUBTABLE
            # with readonly=False.
            # Solution is to open WSRT.MS/SUBTABLE to avoid the locking,
            # which may introduce it's own set of issues
            raise RuntimeError("%s was opened as readonly=False but "
                               "table.iswritable()==False" % table.name())
예제 #3
0
def test_executor_keys():
    """ Test executor keys """
    ex = Executor("foo")
    ex2 = Executor("bar")
    ex3 = Executor("foo")
    ex4 = Executor()

    assert len(_executor_cache) == 3

    assert ex is not ex2
    assert ex is ex3
    assert pickle.loads(pickle.dumps(ex)) is ex3
    assert pickle.loads(pickle.dumps(ex2)) is not ex3

    del ex, ex2, ex3, ex4

    assert len(_executor_cache) == 0