Пример #1
0
 def __init__(self, name):
     self.name = name
     self.depends = Depends()
     self.subscriptions = {}
     self.name2subscription = {}
Пример #2
0
class Subscriptions:
    def __init__(self, name):
        self.name = name
        self.depends = Depends()
        self.subscriptions = {}
        self.name2subscription = {}

    @staticmethod
    def _pathToStr(path):
        if isinstance(path, (tuple, list)) and len(path) == 1:
            path = path[0]
        if bool(path) is False:
            return '/'
        if isinstance(path, (str, unicode)):
            return '/%s' % path
        if path is None:
            return '/'
        return '/%s' % ('/'.join(path))# if path else "/"

    @staticmethod
    def pathIterator(data):
        if isinstance(data, Configuration):
            for path in data.iterpaths():
                yield Subscriptions._pathToStr(path)
        else:
            for path in data:
                yield path

    def addSubscriber(self, callback, component_name, depends_on, *path, **kwargs):
        """
        depends_on: a set of component names
        """
        if component_name in self.name2subscription:
            raise SubscriptionError("[%s] Component already registered" % self.name)
        callback_arg = kwargs.get("callback_arg")
        path = self._pathToStr(path)
        subscription = Subscription(component_name, callback, callback_arg)
        self.name2subscription[component_name] = subscription

        if depends_on:
            self.depends.addDepObject(component_name, depends_on)

        if path not in self.subscriptions:
            self.subscriptions[path] = set()
        self.subscriptions[path].add(subscription)

    def match(self, data, match_all=False):
        """
        @arg data: a Configuration OR paths
        """
        self.cleanup_paths()
        if not self.subscriptions:
            return tuple()

        if match_all:
            names = [item.name for item in self.name2subscription.values()]
        else:
            names = [item.name for item in self._match(data)]
        alldeps = self.depends.getDependancesForMany(names)
        subscribers = [self.name2subscription[item] for item in alldeps]
        return [item.data() for item in subscribers]

    def _match(self, data):
        """
        @arg data: a Configuration OR paths
        """
        subscribers = set()

        for path in Subscriptions.pathIterator(data):
            if path.startswith(VIRTUAL_PATH):
                path = path.replace(VIRTUAL_PATH, '/', 1)
            for subscribed_path in self.subscriptions:
                if not subscribed_path.startswith(path):
                    continue
                for subscription in self.subscriptions[subscribed_path]:
                    subscribers.add(subscription)
                    subscription.paths.append(path)
        return subscribers

    def iterSubscriptions(self):
        for subscriptions in self.subscriptions.itervalues():
            for subscription in subscriptions:
                yield subscription

    def cleanup_paths(self):
        for subscription in self.iterSubscriptions():
            subscription.paths = []