Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > dca483b59ba61f3fa092de932ddd570e > files > 745

nuface-2.0.14-2mdv2009.1.i586.rpm

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Copyright(C) 2007 INL
Written by Damien Boucard <damien.boucard AT inl.fr>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 3 of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.

---
relation.py is a module which dynamically manages multi-lateral relations.
"""

class RelationManager(list):
    pass


class Relation:
    def __init__(self, manager=None):
        self.manager = default_manager
        if manager is not None:
            if not isinstance(manager, RelationManager):
                raise ValueError("'manager' argument must be a %s instance; given: %s (%s)"
                     %(default_manager.__class__.name, manager, type(manager)))
            self.manager = manager
        self.manager.append(self)

class RelationSet:
    def __init__(self, relation_type=Relation, manager=None, **kw):
        """
        Filtered list of relations. Filtering is made on type of relation
        (class given to isinstance) and/or the value of one or several
        relation instance attribute.

        Example of usage:
        >>> class Test(Relation):
        ...     def __init__(self, a, b):
        ...         Relation.__init__(self)
        ...         self.a = a
        ...         self.b = b
        ...     def __str__(self): return "%s-%s" %(self.a, self.b)
        >>> a1 = "A"
        >>> b1 = "1"
        >>> a2 = "B"
        >>> b2 = "2"
        >>> Test(a1, b1) #doctest: +ELLIPSIS
        <__main__.Test instance at 0x...>
        >>> Test(a1, b2) #doctest: +ELLIPSIS
        <__main__.Test instance at 0x...>
        >>> Test(a2, b2) #doctest: +ELLIPSIS
        <__main__.Test instance at 0x...>
        >>> str(RelationSet(relation_type=Test, a=a1))
        "['A-1', 'A-2']"
        >>> str(RelationSet(relation_type=Test, a=a2))
        "['B-2']"
        >>> str(RelationSet(relation_type=Test, a=a1, b=b1))
        "['A-1']"
        >>> str(RelationSet(relation_type=Test))
        "['A-1', 'A-2', 'B-2']"

        Filter can be made on attributes of related objects, by passing keyword
        arguments containing double-underscore "__". Each "__" is interpreted
        as a "." in the normal Python syntax.

        Exemple of recursive lookup:
        >>> del default_manager[:]
        >>> class N:
        ...     def __init__(self, n, salt):
        ...         self.n = n
        ...         self.salt = salt
        ...     def __str__(self): return "N%s(%s)" %(self.n, self.salt)
        >>> Test(a1, N(1, "Abc"))
        <__main__.Test instance at 0x...>
        >>> Test(a1, N(2, "Def"))
        <__main__.Test instance at 0x...>
        >>> Test(a1, N(2, "Ghi"))
        <__main__.Test instance at 0x...>
        >>> str(RelationSet())
        "['A-N1(Abc)', 'A-N2(Def)', 'A-N2(Ghi)']"
        >>> str(RelationSet(b__n=1))
        "['A-N1(Abc)']"
        >>> str(RelationSet(b__n=2))
        "['A-N2(Def)', 'A-N2(Ghi)']"
        """
        self.attributes = kw
        if not issubclass(relation_type, Relation):
            raise ValueError("'relation_type' argument must be a subclass of relation.Relation; given: %s"
                                                     %(relation_type.__name__))
        self.relation_type = relation_type
        self.manager = default_manager
        if manager is not None:
            if not isinstance(manager, RelationManager):
                raise ValueError("'manager' argument must be a %s instance; given: %s (%s)"
                     %(default_manager.__class__.name, manager, type(manager)))
            self.manager = manager

    def __iter__(self):
        for relation in self.manager:
            if not isinstance(relation, self.relation_type):
                continue
            has_attr = True
            for attr_str, expected_value in self.attributes.iteritems():
                attr_list = attr_str.split("__")
                attr_value = relation
                for attr_name in attr_list:
                    if not hasattr(attr_value, attr_name):
                        has_attr = False
                        break
                    attr_value = getattr(attr_value, attr_name)
                if not has_attr or attr_value != expected_value:
                    has_attr = False
                    break
            if has_attr:
                yield relation

    def __len__(self):
        return len([str(relation) for relation in self])

    def __str__(self):
        return str([str(relation) for relation in self])

default_manager = RelationManager()

if __name__ == "__main__":
    from doctest import testmod, ELLIPSIS
    from sys import exit
    failure, nb_test = testmod(optionflags=ELLIPSIS)
    if failure:
        exit(1)