def test_copy_class():
    from xoutil import Unset
    from xoutil.eight import _py3
    from xoutil.eight.meta import metaclass
    from xoutil.objects import copy_class

    u = str if _py3 else unicode

    class MetaFoo(type):
        pass

    class Foo(metaclass(MetaFoo)):
        a = 1
        b = 2
        c = 3
        d = 4

    class Baz(Foo):
        e = 5

    index = {k: getattr(Foo, k) for k in 'abcd'}
    Bar = copy_class(Foo)
    assert Bar.a == Foo.a and Bar.b and Bar.c and Bar.d

    Egg = copy_class(Foo, ignores=['b', 'c'])
    assert getattr(Egg, 'b', Unset) is Unset

    Egg = copy_class(Foo, ignores=[lambda k: index.get(k) and index.get(k) > 2])
    assert Egg.a == Foo.a
    assert getattr(Egg, 'c', Unset) is Unset

    Named = copy_class(Foo, new_name='Named')
    assert Named.__name__ == 'Named'

    Named = copy_class(Foo, new_name=u('Named'))
    assert Named.__name__ == 'Named'

    import fnmatch
    pattern = lambda attr: fnmatch.fnmatch(attr, 'a*')
    Egg = copy_class(Foo, ignores=[pattern])
    assert getattr(Egg, 'a', Unset) is Unset

    import re
    _pattern = re.compile('^a')
    pattern = lambda attr: _pattern.match(attr)
    Egg = copy_class(Foo, ignores=[pattern])
    assert getattr(Egg, 'a', Unset) is Unset
Beispiel #2
0
def thesefy(target):
    '''Allow an object to participate in queries.

    Example as a wrapper::

        class People(object):
            # ...
            pass

        query = (who for who in thesefy(People))

    Example as a decorator::

        @thesefy
        class People(object):
            pass

        query = (who for who in People)

    If your classes already support the iterable protocol (i.e implement
    ``__iter__``) this does nothing.

    '''
    if getattr(target, '__iter__', None):
        return target

    class new_meta(type(target)):
        def __iter__(self):
            return (x for x in this if isinstance(x, self))

        def next(self):
            raise StopIteration
        __next__ = next

    from xoutil.objects import copy_class
    new_class = copy_class(target, meta=new_meta)
    return new_class
Beispiel #3
0
def thesefy(target, make_subquery=True):
    '''Allow an object to participate in queries.

    Example as a wrapper::

        class People:
            # ...
            pass

        query = (who for who in thesefy(People))

    Example as a decorator::

        @thesefy
        class People:
            pass

        query = (who for who in People)

    If `target` already support the iterable protocol (i.e implement
    ``__iter__``), return it unchanged.

    If `make_subquery` is True, then the query shown above will be equivalent
    to::

        query = (who for who in (x for x in this if isinstance(x, People)))

    If `make_subquery` is False, `thesefy` injects an ``__iter__()`` that
    simply returns the same object and a ``next()`` method that immediately
    stops the iteration.

    Notice that in order to use `make_subquery` you call `thesefy`:func: as a
    decorator-returning function::

        class Person:
            pass

        query = (x for x in thesefy(make_subquery=False)(Person))

        # or simply as a decorator

        @thesefy(make_subquery=False)
        class Person:
            pass

    '''
    if getattr(target, '__iter__', None):
        return target

    class new_meta(type(target)):
        if make_subquery:
            def __iter__(self):
                return (x for x in this if isinstance(x, self))
        else:
            def __iter__(self):
                return self

            def next(self):
                raise StopIteration
            __next__ = next

    from xoutil.objects import copy_class
    new_class = copy_class(target, meta=new_meta)
    return new_class