开发者

Python Event-Category Mapping Design

I am working on some code to organize our event definition/category mapping. Our goal is to be able to define "event names" as well as associate categories, its pretty much a static process. What we want is people using constants and not a bunch of strings everywhere. We also need somewhere to validate events/categories, as well as do some lookup things like getting events by categories and vice versa.

class EventMapping(object)
    def __init__(self, name, categories):
        self.name =  name
        self.categories=  categories
        EventRegistry.register(self)

    def __eq__(self, obj):
        if(isinstance(obj, str)):
            return obj==self.name
        if(isinstance(obj, EventMapping)):
            return obj.name ==self.name 
               and obj.categories==self.categories
        return False

    def __repr__(self):
        return self.name   

class Event():
    class MyCompontent():
        ComponentEvent = EventMapping("ComponentEvent", None)
        ComponentEventWCategory = EventMapping("ComponentEvent"
             , [Category.MyComponent.Useful])
    class Data():
         Created =EventMapping("Created", [Category.Data.All, Category.Data.Count]
         Updated= EventMapping("Updated", [Category.Data.All]
         Deleted= EventMapping("Deleted", [Category.Data.All, Category.Data.Count]

class Category():
    class MyComponent():
        Useful = "Useful"
    class Data():
        All= "All" 
        Count= "Count" 

class EventRegistry():
    @staticmethod
    def register( eventMapping):
        eventName= eventMapping.name
        #store locally...

    @staticmethod
    def events(category):
        #retreive events by category

    @staticmethod
    def category(event_name):
        #retreive categories by event name

There are a couple of things I don't like:

  1. In the EventRegistry class I store storing them twice, once in an Event Dictionary key being the name, and value a list of categories. The second is the 开发者_如何转开发opposite Category dictionary keyed by category name and a list of events. Is there a better way to achieve this? I basically need an easy way to look up by name or category.

  2. Should I just create two registries? One for Categories one for Events?

  3. When it comes to using the Events we do it like:

    self.subscribe(Event.MyComponent.Useful) self.subscribe(Category.MyComponent.Useful)

we then use the registry to validate the event exists, as well as deliver the message. Is there an easier way to achieve the package like namespaces?

Just looking for some feedback on better ways to do it, or a pattern to follow. I have searched around and can't find anything. Even if you know of some module i can look at and get a better feel for a better way to do it, ill be glad to look into that as well.


Why don't you go for something more pythonic?

from collections import defaultdict


_linked = defaultdict(set)


class Linkable(object):

    def link(self, *others):
        _linked[self].update(others)
        for each in others:
            _linked[each].add(self)

    def unlink(self, *others):
        _linked[self].difference_update(others)
        for each in others:
            _linked[each].discard(self)

    def links(self):
        return set(_linked[self])


class NameHierarchy(object):

    def __init__(self, name, parent=None):
        self.name = name
        self.parent = parent or self
        self.path = parent.path + [self] if parent else [self]

    def __str__(self):
        return '.'.join(each.name for each in self.path)

    def add(self, name):
        if name not in self.__dict__:
            setattr(self, name, self.__class__(name, self))


class LinkedNameHierarchy(Linkable, NameHierarchy):
    pass


Category = LinkedNameHierarchy('Category')

Category.add('MyComponent')
Category.MyComponent.add('Useful')

Category.add('Data')
Category.Data.add('All')
Category.Data.add('Count')

Event = LinkedNameHierarchy('Event')

Event.add('MyComponent')
Event.MyComponent.add('ComponentEvent')
Event.MyComponent.add('ComponentEventWCategory')

Event.MyComponent.ComponentEventWCategory.link(Category.MyComponent.Useful)

Event.add('Data')
Event.Data.add('Created')
Event.Data.add('Updated')
Event.Data.add('Deleted')

Event.Data.Created.link(Category.Data.All, Category.Data.Count)
Event.Data.Updated.link(Category.Data.All)
Event.Data.Deleted.link(Category.Data.All, Category.Data.Count)


def show_links():
    print
    print '----8<--------8<--------8<--------8<--------8<--------8<----'
    for k, v in sorted(_linked.iteritems(), key=lambda x:str(x[0])):
        print
        print k
        for each in sorted(v, key=str):
            print '        ', each

show_links()

Event.Data.Created.unlink(Category.Data.Count)

show_links()

There are circular references, which normally would cause memory leakage. In this case it's ok though, because those objects presumably live as long as the proram runs anyhow.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜