root/trunk/RBFoundation/RBFoundation/Utilities.py

Revision 724, 6.8 kB (checked in by sholloway, 5 years ago)

*** empty log message ***

Line 
1 #!/usr/bin/env python
2 ##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3 ##~ License
4 ##~
5 ##- The RuneBlade Foundation library is intended to ease some
6 ##- aspects of writing intricate Jabber, XML, and User Interface (wxPython, etc.)
7 ##- applications, while providing the flexibility to modularly change the
8 ##- architecture. Enjoy.
9 ##~
10 ##~ Copyright (C) 2002  TechGame Networks, LLC.
11 ##~
12 ##~ This library is free software; you can redistribute it and/or
13 ##~ modify it under the terms of the BSD style License as found in the
14 ##~ LICENSE file included with this distribution.
15 ##~
16 ##~ TechGame Networks, LLC can be reached at:
17 ##~ 3578 E. Hartsel Drive #211
18 ##~ Colorado Springs, Colorado, USA, 80920
19 ##~
20 ##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21
22 """Just a handy sub-tool set of tools.  They just clean up the code a bit more..."""
23
24 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 #~ Imports
26 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27
28 from __future__ import generators
29 import types
30
31 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
32 #~ Constants / Variables / Etc.
33 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
34
35 _collectiontypes = (list, tuple, types.GeneratorType)
36
37 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
38 #~ Definitions
39 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
40
41 def isIterable(item):
42     if isinstance(item, _collectiontypes):
43         return True
44     elif hasattr(item, '__iter__'):
45         return True
46     else:
47         return False
48
49 def asIterable(item):
50     if isinstance(item, _collectiontypes):
51         return item
52     elif hasattr(item, '__iter__'):
53         return item
54     else:
55         return [item]
56
57 def irip(collection):
58     collection = map(iter, collection)
59     try:
60         while collection:
61             section = []
62             for coll in collection:
63                 section.append(coll.next())
64             yield section
65     except StopIteration:
66         pass
67
68 def rip(collection):
69     return list(irip(collection))
70
71 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
72
73 def flatten(collection, level=1):
74     if isinstance(collection, (list, tuple)):
75         if level:
76             return [each for item in collection for each in flatten(item, level-1)]
77         else:
78             return collection
79     else:
80         return [collection]
81
82 def flattenall(collection):
83     return flatten(collection, -1)
84
85 def cleanupstrlst(datalst, FilterResult=0):
86     """Strips characters from a list of strings, and drops subsequent empty strings.
87
88     >>> cleanupstrlst(["   this  ", "  is  ", " \\t fun \\t \\r", "  \\n \\r \\t test\\t\\t"])
89     ['this', 'is', 'fun', 'test']
90     """
91     result = map(str.strip, datalst)
92     if FilterResult:
93         return filter(None, result)
94     else: return result
95
96 def joinclean(joinstr, data, *args, **kw):
97     """Uses cleanupstrlst, then joins the result using joinstr.
98     If data is simply a string, then the data is splitup using strtolist.
99
100     >>> joinclean(".", ["   this  ", "  is  ", " \\t fun \\t \\r", "  \\n \\r \\t test\\t\\t"])
101     'this.is.fun.test'
102     >>> joinclean("-", "data, , fun  ,   data   ,   oh\\t\\t\\t ,please  \\t, \\r\\n can \\t  ,  I have more data!   ")
103     'data--fun-data-oh-please-can-I have more data!'
104
105     """
106     if isinstance(data, list):
107         return joinstr.join(cleanupstrlst(data, *args, **kw))
108     elif isinstance(data, (str, unicode)):
109         return joinstr.join(strtolist(data, *args, **kw))
110
111 def strtolist(data, splitchar=',', *args, **kw):
112     """Splits a dilimited string, then runs the result through cleanupstrlst.
113
114     >>> strtolist("data, , fun  ,   data   ,   oh\\t\\t\\t ,please  \\t, \\r\\n can \\t  ,  I have more data!   ")
115     ['data', '', 'fun', 'data', 'oh', 'please', 'can', 'I have more data!']
116     """
117
118     return cleanupstrlst(data.split(splitchar), *args, **kw)
119
120 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
121 #~ Tree Iteration/Searching
122 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
123
124 class TreeDict(dict):
125     def addleaf(self, leaf):
126         self[None] = leaf
127     def addbranch(self, key, branch):
128         self[key] = branch
129
130 class TreeIterator(object):
131     TreeFactory = TreeDict
132
133     def __init__(self, root=()):
134         self.SetRoot(root)
135
136     def GetRoot(self, root):
137         return self._root
138     def SetRoot(self, root):
139         self._root = root
140
141     def isBranch(self, key, value):
142         return bool(key)
143
144     def asTree(self):
145         resulttree = self.TreeFactory()
146         workqueue = [(resulttree, self._GetRootAsIter())]
147         while workqueue:
148             tree, itemcollection = workqueue.pop()
149             for key, item in itemcollection:
150                 if self.isBranch(key, item):
151                     try:
152                         itemtree=tree[key]
153                     except LookupError:
154                         itemtree=self.TreeFactory()
155                         tree.addbranch(key, itemtree)
156                     workqueue.append((itemtree, item))
157                 else:
158                     tree.addleaf(item)
159         return resulttree
160
161     def iterByDepth(self, noDuplicates=False, yieldkeys=False):
162         iterResult = self._iter(yieldkeys, -1)
163         if noDuplicates:
164             return self.iterFilterDuplicates(iterResult, yieldkeys)
165         else:
166             return iterResult
167
168     def iterByBreadth(self, noDuplicates=False, yieldkeys=False):
169         iterResult = self._iter(yieldkeys, 0)
170         if noDuplicates:
171             return self.iterFilterDuplicates(iterResult, yieldkeys)
172         else:
173             return iterResult
174
175     def iterFilterDuplicates(self, iterable, resultDecorated=False):
176         if resultDecorated:
177             getvalue = lambda x:x[-1]
178         else:
179             getvalue = lambda x:x
180
181         allresults = {}
182         for item in iterable:
183             value = getvalue(item)
184             if value not in allresults:
185                 allresults[value]=None
186                 yield item
187
188     def _GetRootAsIter(self):
189         if callable(self._root):
190             return self._root()
191         else:
192             return iter(self._root)
193
194     def _iter(self, yieldkeys=False, popindex=-1):
195         workqueue = [((), self._GetRootAsIter())]
196         while workqueue:
197             path, itemcollection = workqueue.pop(popindex)
198             tempqueue = []
199             for key, item in itemcollection:
200                 newkey = path+(key,)
201                 if self.isBranch(key, item):
202                     tempqueue.append((newkey, item))
203                 elif yieldkeys:
204                     yield newkey, item
205                 else:
206                     yield item
207             if popindex<0:
208                 tempqueue.reverse()
209             workqueue.extend(tempqueue)
210
211 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
212 #~ Testing
213 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
214
215 if __name__=='__main__':
216     print "Testing..."
217     import doctest, Utilities
218     doctest.testmod(Utilities)
219     print "Test complete."
220
221
Note: See TracBrowser for help on using the browser.