File: topicutils.py

package info (click to toggle)
wxwidgets2.8 2.8.12.1-12
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 242,920 kB
  • sloc: cpp: 1,840,772; xml: 385,749; python: 334,729; makefile: 51,774; ansic: 30,987; sh: 7,716; sql: 258; lex: 194; perl: 139; yacc: 128; pascal: 95; php: 45; lisp: 38; tcl: 38; java: 22; haskell: 20; cs: 18; erlang: 17; ruby: 16; asm: 15; ada: 9; ml: 9; csh: 9
file content (157 lines) | stat: -rw-r--r-- 5,289 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
'''
Various little utilities used by topic-related modules. 

:copyright: Copyright 2006-2009 by Oliver Schoenborn, all rights reserved.
:license: BSD, see LICENSE.txt for details.

'''

from textwrap import TextWrapper, dedent


__all__ = []


UNDERSCORE = '_' # topic name can't start with this
# just want something unlikely to clash with user's topic names
ALL_TOPICS = 'ALL_TOPICS'


class WeakNone:
    '''Pretend to be a weak reference to nothing. Used by ArgsInfos to
    refer to parent when None so no if-else blocks needed. '''
    def __call__(self):
        return None


def smartDedent(paragraph):
    '''
    Dedents a paragraph that is a triple-quoted string. If the first
    line of the paragraph does not contain blanks, the dedent is applied
    to the remainder of the paragraph. This handles the case where a user
    types a documentation string as 
    
    """A long string spanning
    several lines."""
    
    Regular textwrap.dedent() will do nothing to this text because of the 
    first line. Requiring that the user type the docs as """\ with line 
    continuation is not acceptable. 
    '''
    if paragraph.startswith(' '):
        para = dedent(paragraph)
    else:
        lines = paragraph.split('\n')
        exceptFirst = dedent('\n'.join(lines[1:]))
        para = lines[0]+exceptFirst
    return para


class TopicNameInvalid(RuntimeError):
    def __init__(self, name, reason):
        msg = 'Topic name %s invalid: %s' % (name, reason)
        RuntimeError.__init__(self, msg)


import re
_validNameRE = re.compile(r'[a-zA-Z]\w*')


def validateName(topicName):
    '''Raise TopicNameInvalid if nameTuple not valid as topic name.'''
    topicNameTuple = tupleize(topicName)
    if not topicNameTuple:
        reason = 'name tuple must have at least one item!'
        raise TopicNameInvalid(None, reason)

    class topic: pass
    for subname in topicNameTuple:
        if not subname:
            reason = 'can\'t contain empty string or None'
            raise TopicNameInvalid(topicNameTuple, reason)

        if subname.startswith(UNDERSCORE):
            reason = 'must not start with "%s"' % UNDERSCORE
            raise TopicNameInvalid(topicNameTuple, reason)

        if subname == ALL_TOPICS:
            reason = 'string "%s" is reserved for root topic' % ALL_TOPICS
            raise TopicNameInvalid(topicNameTuple, reason)

        if _validNameRE.match(subname) is None:
            reason = 'element #%s ("%s") has invalid characters' % \
                (1+list(topicNameTuple).index(subname), subname)
            raise TopicNameInvalid(topicNameTuple, reason)


def stringize(topicNameTuple):
    '''If topicName is a string, do nothing and return it 
    as is. Otherwise, convert it to one, using dotted notation,
    i.e. ('a','b','c') => 'a.b.c'. Empty name is not allowed 
    (ValueError). The reverse operation is tupleize(topicName).'''
    if isinstance(topicNameTuple, str):
        return topicNameTuple
    
    try:
        name = '.'.join(topicNameTuple)
    except Exception, exc:
        raise TopicNameInvalid(topicNameTuple, str(exc))
    
    return name


def tupleize(topicName):
    '''If topicName is a tuple of strings, do nothing and return it 
    as is. Otherwise, convert it to one, assuming dotted notation 
    used for topicName. I.e. 'a.b.c' => ('a','b','c'). Empty 
    topicName is not allowed (ValueError). The reverse operation 
    is stringize(topicNameTuple).'''
    # assume name is most often str; if more often tuple, 
    # then better use isinstance(name, tuple)
    if isinstance(topicName, str): 
        topicTuple = tuple(topicName.split('.'))
    else:
        topicTuple = tuple(topicName) # assume already tuple of strings
        
    if not topicTuple:
        raise TopicNameInvalid(topicTuple, "Topic name can't be empty!")
                
    return topicTuple


def versionedImport(modName, g, *varNames, **fromNames):
    '''Import a versioned pubsub module, ie one that has API different
    depending on message protocol used. Example: say a module 'foo.py' does

        from topicutils import versionedImport
        versionedImport('moduleName', globals(), 'class1', obj2='obj1')

    This will import the correct version of 'moduleName' and put its 'class1'
    and 'obj1' objects into foo's module namespace such that foo.class1
    and foo.obj2 will be the correct class1 and obj1 for messaging protocol
    used in pubsub.
    '''
    # associate message protocol to file suffixes
    impVers = dict(
        kwargs  = 'p2',
        arg1 = 'p1')
    # create real module name to import
    import policies
    versionStr = impVers[policies.msgDataProtocol]
    fullModName = "%s_%s" % (modName, versionStr)
    # do import
    modObj = __import__(fullModName)
    
    def impSymbol(nameInG, nameInMod = None):
        nameInMod = nameInMod or nameInG # assume same if not specified
        varVal = getattr(modObj, nameInMod, None)
        if varVal is None:
            raise ValueError('No "%s" in %s' % (nameInMod, modObj))
        g[nameInG] = varVal

    # import given symbols (if any) into g dict
    for varName in varNames:
        impSymbol(varName)
    for nameInG, nameInMod in fromNames.iteritems():
        impSymbol(nameInG, nameInMod)