Exemplo n.º 1
0
class EnumeratedSetFromIterator_method_caller(Decorator):
    r"""
    Caller for decorated method in class.

    INPUT:

    - ``inst`` -- an instance of a class

    - ``f`` -- a method of a class of ``inst`` (and not of the instance itself)

    - ``name`` -- optional -- either a string (which may contains substitution
      rules from argument or a function args,kwds -> string.

    - ``options`` -- any option accepted by :class:`EnumeratedSetFromIterator`
    """
    def __init__(self, inst, f, name=None, **options):
        r"""
        Initialize ``self``.

        TESTS::

            sage: from sage.sets.set_from_iterator import DummyExampleForPicklingTest
            sage: d = DummyExampleForPicklingTest()
            sage: d.f()
            {10, 11, 12, 13, 14, ...}

        It is possible to pickle/unpickle the class and the instance::

            sage: loads(dumps(DummyExampleForPicklingTest))().f()
            {10, 11, 12, 13, 14, ...}
            sage: loads(dumps(d)).f()
            {10, 11, 12, 13, 14, ...}

        But not the enumerated set::

            sage: loads(dumps(d.f())) # py2
            Traceback (most recent call last):
            ...
            PicklingError: Can't pickle <... 'function'>: attribute lookup __builtin__.function failed
            sage: loads(dumps(d.f())) # py3
            Traceback (most recent call last):
            ...
            _pickle.PicklingError: Can't pickle <function DummyExampleForPicklingTest.f at ...>: it's not the same object as sage.sets.set_from_iterator.DummyExampleForPicklingTest.f
        """
        self.inst = inst
        self.f = f
        self.af = ArgumentFixer(self.f)
        if hasattr(f, "__name__"):
            self.__name__ = f.__name__
        else:
            self.__name__ = f.__name__
        self.__module__ = f.__module__

        self.name = name
        self.options = options

    def __call__(self,*args,**kwds):
        r"""
        Returns an instance of :class:`EnumeratedSetFromIterator` with
        proper argument.

        TESTS::

            sage: from sage.sets.set_from_iterator import set_from_method
            sage: class A:
            ....:  @set_from_method(name = lambda self,n: str(self)*n)
            ....:  def f(self,n):
            ....:      return xsrange(n)
            ....:  def __repr__(self):
            ....:      return "A"
            sage: a = A()
            sage: a.f(3)                         # indirect doctest
            AAA
            sage: A.f(a,3)                       # indirect doctest
            AAA
            sage: [x for x in a.f(6)]            # indirect doctest
            [0, 1, 2, 3, 4, 5]
        """
        if self.inst is not None:
            args = (self.inst,) + args
        if self.name:
            if isinstance(self.name,str):
                aa,kk = self.af.fix_to_named(*args,**kwds)
                name = self.name%dict(kk)
            else:
                name = self.name(*args, **kwds)
            return EnumeratedSetFromIterator(self.f, args, kwds, name, **self.options)
        return EnumeratedSetFromIterator(self.f, args, kwds, **self.options)

    def __get__(self, inst, cls):
        r"""
        Get a :class:`EnumeratedSetFromIterator_method_caller` bound to a
        specific instance of the class of the cached method.

        .. NOTE::

            :class:`EnumeratedSetFromIterator_method_caller` has a separate
            ``__get__`` because of the special behavior of category framework
            for element classes which are not of extension type (see
            :meth:`sage.structure.element.Element.__get__`).

        TESTS::

            sage: from sage.sets.set_from_iterator import set_from_method
            sage: class A:
            ....:    stop = 10000
            ....:    @set_from_method
            ....:    def f(self,start):
            ....:        return xsrange(start,self.stop)
            sage: a = A()
            sage: A.f(a,4)
            {4, 5, 6, 7, 8, ...}

            sage: class B:
            ....:    stop = 10000
            ....:    @set_from_method(category=FiniteEnumeratedSets())
            ....:    def f(self,start):
            ....:        return xsrange(start,self.stop)
            sage: b = B()
            sage: B.f(b,2)
            {2, 3, 4, 5, 6, ...}
        """
        return EnumeratedSetFromIterator_method_caller(
                inst, self.f,
                self.name,
                **self.options)
Exemplo n.º 2
0
class EnumeratedSetFromIterator_method_caller(Decorator):
    r"""
    Caller for decorated method in class.

    INPUT:

    - ``inst`` -- an instance of a class

    - ``f`` -- a method of a class of ``inst`` (and not of the instance itself)

    - ``name`` -- optional -- either a string (which may contains substitution
      rules from argument or a function args,kwds -> string.

    - ``options`` -- any option accepted by :class:`EnumeratedSetFromIterator`
    """
    def __init__(self, inst, f, name=None, **options):
        r"""
        Initialize ``self``.

        TESTS::

            sage: from sage.sets.set_from_iterator import DummyExampleForPicklingTest
            sage: d = DummyExampleForPicklingTest()
            sage: d.f()
            {10, 11, 12, 13, 14, ...}

        It is possible to pickle/unpickle the class and the instance::

            sage: loads(dumps(DummyExampleForPicklingTest))().f()
            {10, 11, 12, 13, 14, ...}
            sage: loads(dumps(d)).f()
            {10, 11, 12, 13, 14, ...}

        But not the enumerated set::

            sage: loads(dumps(d.f()))
            Traceback (most recent call last):
            ...
            PicklingError: Can't pickle <type 'function'>: attribute lookup __builtin__.function failed
        """
        self.inst = inst
        self.f = f
        self.af = ArgumentFixer(self.f)
        if hasattr(f, "__name__"):
            self.__name__ = f.__name__
        else:
            self.__name__ = f.__name__
        self.__module__ = f.__module__

        self.name = name
        self.options = options

    def __call__(self,*args,**kwds):
        r"""
        Returns an instance of :class:`EnumeratedSetFromIterator` with
        proper argument.

        TESTS::

            sage: from sage.sets.set_from_iterator import set_from_method
            sage: class A:
            ...    @set_from_method(name = lambda self,n: str(self)*n)
            ...    def f(self,n):
            ...        return xsrange(n)
            ...    def __repr__(self):
            ...        return "A"
            sage: a = A()
            sage: a.f(3)                         # indirect doctest
            AAA
            sage: A.f(a,3)                       # indirect doctest
            AAA
            sage: [x for x in a.f(6)]            # indirect doctest
            [0, 1, 2, 3, 4, 5]
        """
        if self.inst is not None:
            args = (self.inst,) + args
        if self.name:
            if isinstance(self.name,str):
                aa,kk = self.af.fix_to_named(*args,**kwds)
                name = self.name%dict(kk)
            else:
                name = self.name(*args, **kwds)
            return EnumeratedSetFromIterator(self.f, args, kwds, name, **self.options)
        return EnumeratedSetFromIterator(self.f, args, kwds, **self.options)

    def __get__(self, inst, cls):
        r"""
        Get a :class:`EnumeratedSetFromIterator_method_caller` bound to a
        specific instance of the class of the cached method.

        .. NOTE::

            :class:`EnumeratedSetFromIterator_method_caller` has a separate
            ``__get__`` because of the special behavior of category framework
            for element classes which are not of extension type (see
            :meth:`sage.structure.element.Element.__get__`).

        TESTS::

            sage: from sage.sets.set_from_iterator import set_from_method
            sage: class A:
            ....:    stop = 10000
            ....:    @set_from_method
            ....:    def f(self,start):
            ....:        return xsrange(start,self.stop)
            sage: a = A()
            sage: A.f(a,4)
            {4, 5, 6, 7, 8, ...}

            sage: class B:
            ....:    stop = 10000
            ....:    @set_from_method(category=FiniteEnumeratedSets())
            ....:    def f(self,start):
            ....:        return xsrange(start,self.stop)
            sage: b = B()
            sage: B.f(b,2)
            {2, 3, 4, 5, 6, ...}
        """
        return EnumeratedSetFromIterator_method_caller(
                inst, self.f,
                self.name,
                **self.options)
Exemplo n.º 3
0
class EnumeratedSetFromIterator_function_decorator(Decorator):
    r"""
    Decorator for :class:`EnumeratedSetFromIterator`.

    Name could be string or a function ``(args,kwds) -> string``.

    .. WARNING::

        If you are going to use this with the decorator ``cached_function``,
        you must place the ``cached_function`` first. See the example below.

    EXAMPLES::

        sage: from sage.sets.set_from_iterator import set_from_function
        sage: @set_from_function
        ....: def f(n):
        ....:     for i in range(n):
        ....:         yield i**2 + i + 1
        sage: f(3)
        {1, 3, 7}
        sage: f(100)
        {1, 3, 7, 13, 21, ...}

    To avoid ambiguity, it is always better to use it with a call which
    provides optional global initialization for the call to
    :class:`EnumeratedSetFromIterator`::

        sage: @set_from_function(category=InfiniteEnumeratedSets())
        ....: def Fibonacci():
        ....:     a = 1; b = 2
        ....:     while True:
        ....:         yield a
        ....:         a, b = b, a + b
        sage: F = Fibonacci()
        sage: F
        {1, 2, 3, 5, 8, ...}
        sage: F.cardinality()
        +Infinity

    A simple example with many options::

        sage: @set_from_function(
        ....:      name = "From %(m)d to %(n)d",
        ....:      category = FiniteEnumeratedSets())
        ....: def f(m, n): return xsrange(m,n+1)
        sage: E = f(3,10); E
        From 3 to 10
        sage: E.list()
        [3, 4, 5, 6, 7, 8, 9, 10]
        sage: E = f(1,100); E
        From 1 to 100
        sage: E.cardinality()
        100
        sage: f(n=100,m=1) == E
        True

    An example which mixes together ``set_from_function`` and
    ``cached_method``::

        sage: @cached_function
        ....: @set_from_function(
        ....:  name = "Graphs on %(n)d vertices",
        ....:  category = FiniteEnumeratedSets(),
        ....:  cache = True)
        ....: def Graphs(n): return graphs(n)
        sage: Graphs(10)
        Graphs on 10 vertices
        sage: Graphs(10).unrank(0)
        Graph on 10 vertices
        sage: Graphs(10) is Graphs(10)
        True

    The ``cached_function`` must go first::

        sage: @set_from_function(
        ....:  name = "Graphs on %(n)d vertices",
        ....:  category = FiniteEnumeratedSets(),
        ....:  cache = True)
        ....: @cached_function
        ....: def Graphs(n): return graphs(n)
        sage: Graphs(10)
        Graphs on 10 vertices
        sage: Graphs(10).unrank(0)
        Graph on 10 vertices
        sage: Graphs(10) is Graphs(10)
        False
    """
    def __init__(self, f=None, name=None, **options):
        r"""
        Initialize ``self``.

        TESTS::

            sage: from sage.sets.set_from_iterator import set_from_function
            sage: F = set_from_function(category=FiniteEnumeratedSets())(xsrange)
            sage: TestSuite(F(100)).run()
            sage: TestSuite(F(1,5,2)).run()
            sage: TestSuite(F(0)).run()
        """
        if f is not None:
            self.f = f
            if hasattr(f, "__name__"):
                self.__name__ = f.__name__
            else:
                self.__name__ = f.__name__
            self.__module__ = f.__module__
            self.af = ArgumentFixer(f)
        if name is not None:
            self.name = name
        self.options = options

    def __call__(self, *args, **kwds):
        r"""
        Build a new :class:`EnumeratedSet` by calling ``self.f`` with
        appropriate argument. If ``f`` is ``None``, then returns a new instance
        of :class:`EnumeratedSetFromIterator`.

        EXAMPLES::

            sage: from sage.sets.set_from_iterator import set_from_function
            sage: F = set_from_function(category=FiniteEnumeratedSets())(xsrange)
            sage: F(3)
            {0, 1, 2}
            sage: F(end=7,start=3)
            {3, 4, 5, 6}
            sage: F(10).cardinality()
            10
        """
        if hasattr(self, 'f'): # yet initialized
            if hasattr(self,'name'):
                if isinstance(self.name, str):
                    if args or kwds:
                        _, kk = self.af.fix_to_named(*args,**kwds)
                        name = self.name % dict(kk)
                    else:
                        name = self.name
                else:
                    name = self.name(*args, **kwds)
                return EnumeratedSetFromIterator(self.f, args, kwds, name=name, **self.options)
            return EnumeratedSetFromIterator(self.f, args, kwds, **self.options)

        else: # potential global options
            if args == ():
                f, = kwds.values()
            else:
                assert len(args) == 1
                f = args[0]
            return EnumeratedSetFromIterator_function_decorator(
                f,
                name=getattr(self,'name',None),
                **self.options)
Exemplo n.º 4
0
class EnumeratedSetFromIterator_function_decorator(Decorator):
    r"""
    Decorator for :class:`EnumeratedSetFromIterator`.

    Name could be string or a function ``(args,kwds) -> string``.

    .. WARNING::

        If you are going to use this with the decorator ``cached_function``,
        you must place the ``cached_function`` first. See the example below.

    EXAMPLES::

        sage: from sage.sets.set_from_iterator import set_from_function
        sage: @set_from_function
        ... def f(n):
        ...    for i in xrange(n):
        ...        yield i**2 + i + 1
        sage: f(3)
        {1, 3, 7}
        sage: f(100)
        {1, 3, 7, 13, 21, ...}

    To avoid ambiguity, it is always better to use it with a call which
    provides optional global initialization for the call to
    :class:`EnumeratedSetFromIterator`::

        sage: @set_from_function(category=InfiniteEnumeratedSets())
        ... def Fibonacci():
        ...    a = 1; b = 2
        ...    while True:
        ...       yield a
        ...       a,b = b,a+b
        sage: F = Fibonacci()
        sage: F
        {1, 2, 3, 5, 8, ...}
        sage: F.cardinality()
        +Infinity

    A simple example with many options::

        sage: @set_from_function(
        ...        name = "From %(m)d to %(n)d",
        ...        category = FiniteEnumeratedSets())
        ... def f(m,n): return xsrange(m,n+1)
        sage: E = f(3,10); E
        From 3 to 10
        sage: E.list()
        [3, 4, 5, 6, 7, 8, 9, 10]
        sage: E = f(1,100); E
        From 1 to 100
        sage: E.cardinality()
        100
        sage: f(n=100,m=1) == E
        True

    An example which mixes together ``set_from_function`` and
    ``cached_method``::

        sage: @cached_function
        ... @set_from_function(
        ...    name = "Graphs on %(n)d vertices",
        ...    category = FiniteEnumeratedSets(),
        ...    cache = True)
        ... def Graphs(n): return graphs(n)
        sage: Graphs(10)
        Graphs on 10 vertices
        sage: Graphs(10).unrank(0)
        Graph on 10 vertices
        sage: Graphs(10) is Graphs(10)
        True

    The ``cached_function`` must go first::

        sage: @set_from_function(
        ...    name = "Graphs on %(n)d vertices",
        ...    category = FiniteEnumeratedSets(),
        ...    cache = True)
        ... @cached_function
        ... def Graphs(n): return graphs(n)
        sage: Graphs(10)
        Graphs on 10 vertices
        sage: Graphs(10).unrank(0)
        Graph on 10 vertices
        sage: Graphs(10) is Graphs(10)
        False
    """
    def __init__(self, f=None, name=None, **options):
        r"""
        Initialize ``self``.

        TESTS::

            sage: from sage.sets.set_from_iterator import set_from_function
            sage: F = set_from_function(category=FiniteEnumeratedSets())(xsrange)
            sage: TestSuite(F(100)).run()
            sage: TestSuite(F(1,5,2)).run()
            sage: TestSuite(F(0)).run()
        """
        if f is not None:
            self.f = f
            if hasattr(f, "__name__"):
                self.__name__ = f.__name__
            else:
                self.__name__ = f.__name__
            self.__module__ = f.__module__
            self.af = ArgumentFixer(f)
        if name is not None:
            self.name = name
        self.options = options

    def __call__(self, *args, **kwds):
        r"""
        Build a new :class:`EnumeratedSet` by calling ``self.f`` with
        apropriate argument. If ``f`` is ``None``, then returns a new instance
        of :class:`EnumeratedSetFromIterator`.

        EXAMPLES::

            sage: from sage.sets.set_from_iterator import set_from_function
            sage: F = set_from_function(category=FiniteEnumeratedSets())(xsrange)
            sage: F(3)
            {0, 1, 2}
            sage: F(end=7,start=3)
            {3, 4, 5, 6}
            sage: F(10).cardinality()
            10
        """
        options = self.options

        if hasattr(self, 'f'): # yet initialized
            if hasattr(self,'name'):
                if isinstance(self.name,str):
                    if args or kwds:
                        _,kk = self.af.fix_to_named(*args,**kwds)
                        name = self.name%dict(kk)
                    else:
                        name = self.name
                else:
                    name = self.name(*args,**kwds)
                return EnumeratedSetFromIterator(self.f, args, kwds, name=name, **self.options)
            return EnumeratedSetFromIterator(self.f, args, kwds, **self.options)

        else: # potential global options
            if args == ():
                assert len(kwds.keys()) == 1
                f = kwds.values()[0]
            else:
                assert len(args) == 1
                f = args[0]
            return EnumeratedSetFromIterator_function_decorator(
                f,
                name=getattr(self,'name',None),
                **self.options)