PageRenderTime 93ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/src/misc.py

https://github.com/kerspoon/laos
Python | 347 lines | 299 code | 10 blank | 38 comment | 1 complexity | 852ceb663127c4699b45ecda5c361f43 MD5 | raw file
  1. #! /usr/local/bin/python
  2. #==============================================================================
  3. # Copyright (C) 2009 James Brooks (kerspoon)
  4. #
  5. # This program is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; version 2 dated June, 1991.
  8. #
  9. # This software is distributed in the hope that it will be useful, but
  10. # WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANDABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. # General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License
  15. # along with this program; if not, write to the Free Software Foundation,
  16. # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  17. #==============================================================================
  18. """ Package info:
  19. James Brooks (kerspoon)
  20. Misc utilities.
  21. """
  22. #==============================================================================
  23. # Imports:
  24. #==============================================================================
  25. import sys
  26. import re
  27. import os
  28. import logging
  29. import itertools
  30. import traceback
  31. from collections import defaultdict
  32. #==============================================================================
  33. # Logging:
  34. #==============================================================================
  35. logging.basicConfig(stream=sys.stdout, level=logging.DEBUG,
  36. format="%(levelname)s: %(message)s")
  37. logger = logging.getLogger(__name__)
  38. #==============================================================================
  39. # Grem: regexp file deleter
  40. #==============================================================================
  41. def grem(path, pattern, test=False):
  42. """remove all folders/files in 'path' thatmatches the
  43. regexp 'pattern'. test prints out names only.
  44. <http://docs.python.org/library/re.html>
  45. it's highly recommended that you use raw strings for
  46. all but the simplest expressions.
  47. """
  48. pattern = re.compile(pattern)
  49. for each in os.listdir(path):
  50. if pattern.search(each):
  51. name = os.path.join(path, each)
  52. try:
  53. if not test: os.remove(name)
  54. # logger.info("Grem removed " + name)
  55. except:
  56. if not test:
  57. grem(name, '')
  58. os.rmdir(name)
  59. # logger.info("Grem removed dir " + name)
  60. def test_grem():
  61. grem(".", r".*\.pyc", True)
  62. grem(".", r"rts_[1234567890]{2}\.txt", True)
  63. # test_grem()
  64. #==============================================================================
  65. # split_every
  66. #==============================================================================
  67. def split_every(n, iterable):
  68. """
  69. split_every :: Int -> [e] -> [[e]]
  70. @'split_every' n@ splits a list into length-n pieces. The last
  71. piece will be shorter if @n@ does not evenly divide the length of
  72. the list.
  73. from: http://stackoverflow.com/questions/1915170#1915307
  74. """
  75. i = iter(iterable)
  76. piece = list(itertools.islice(i, n))
  77. while piece:
  78. yield piece
  79. piece = list(itertools.islice(i, n))
  80. def TEST_split_every():
  81. # should not enter infinite loop with generators and lists
  82. split_every(itertools.count(), 10)
  83. split_every(range(1000), 10)
  84. # last piece must be shorter if n does not evenly divide
  85. assert list(split_every(5, range(9))) == [[0, 1, 2, 3, 4], [5, 6, 7, 8]]
  86. # should give same correct results with generators
  87. tmp = itertools.islice(itertools.count(), 9)
  88. assert list(split_every(5, tmp)) == [[0, 1, 2, 3, 4], [5, 6, 7, 8]]
  89. # should work with empty list.
  90. assert list(split_every(100, [])) == []
  91. # TEST_split_every()
  92. #==============================================================================
  93. # duplicates_exist
  94. #==============================================================================
  95. def duplicates_exist(iterable):
  96. """
  97. duplicates_exist [x] -> Bool
  98. Are there two or more elements in this list that are equal?
  99. could sort then compare adjacent or by building a count of elements and
  100. making sure that count is all 1.
  101. """
  102. tally = defaultdict(int)
  103. for x in iterable:
  104. tally[x] += 1
  105. return not all(count == 1 for count in tally.values())
  106. def TEST_duplicates_exist():
  107. assert duplicates_exist([0, 1, 2, 3]) == False
  108. assert duplicates_exist([2, 1, 2, 3]) == True
  109. assert duplicates_exist([1, 1, 2, 3]) == True
  110. assert duplicates_exist([1, 1, 1, 1]) == True
  111. assert duplicates_exist([-4, 8, 2, 7]) == False
  112. # TEST_duplicates_exist()
  113. #==============================================================================
  114. # as_csv :: [T], str -> str
  115. #==============================================================================
  116. def as_csv(iterable, sep=" "):
  117. """a string of each item seperated by 'sep'"""
  118. return sep.join(str(x) for x in list(iterable))
  119. def TEST_as_csv():
  120. assert as_csv([1, 2, 3], ", ") == "1, 2, 3"
  121. assert as_csv([1], "abc") == "1"
  122. assert as_csv(xrange(5), "_") == "0_1_2_3_4"
  123. # TEST_as_csv()
  124. #==============================================================================
  125. # struct:
  126. #==============================================================================
  127. class struct(object):
  128. """
  129. e.g. a simple use of the struct class:
  130. class Bus(struct):
  131. entries = "bus_id fail_rate repair_rate".split()
  132. types = "int real real".split()
  133. bus = read_struct(Bus, "101 0.025 13".split())
  134. assert bus.bus_id == 101
  135. assert abs(bus.fail_rate - 0.025) > 0.0001
  136. assert abs(bus.repair_rate - 13) > 0.0001
  137. assert str(bus) == "101 0.025 13"
  138. """
  139. def __init__(self, tokens=None):
  140. """if we are given tokens (a dict of entries) then fill them in
  141. and check we have filled all of them.
  142. if we have self.types convert all entries to correct type
  143. """
  144. EnsureIn("entries", dir(self), "structs must have `entries`")
  145. if "types" in dir(self):
  146. EnsureEqual(len(self.entries), len(self.types))
  147. if tokens:
  148. self.dict_fill(tokens)
  149. self.check_entries()
  150. if "types" in dir(self):
  151. self.convert_types()
  152. def __str__(self):
  153. """a simple space seperated string with entries in the
  154. same order as 'entries'
  155. """
  156. return as_csv([self.__dict__[x] for x in self.entries], " ")
  157. def dict_fill(self, kwds):
  158. """fill in all 'entries' using the dict 'kwds'"""
  159. self.__dict__.update(kwds)
  160. def convert_types(self):
  161. """convert all entries into the proper types using self.types"""
  162. self.typemap = dict(zip(self.entries, self.types))
  163. # typemap = {'bus_id':'int',
  164. # 'fail_rate':'real',
  165. # 'repair_rate':'real'}
  166. for member in self.entries:
  167. if self.typemap[member] == "int":
  168. self.__dict__[member] = int(self.__dict__[member])
  169. elif self.typemap[member] == "real":
  170. self.__dict__[member] = float(self.__dict__[member])
  171. elif self.typemap[member] == "bool":
  172. self.__dict__[member] = bool(self.__dict__[member])
  173. elif self.typemap[member] == "str":
  174. self.__dict__[member] = str(self.__dict__[member])
  175. else:
  176. raise Error("bad datatype. expected (int, real, bool, str) got " +
  177. self.typemap[member])
  178. def check_entries(self):
  179. """make sure that all the entries are added"""
  180. for member in self.entries:
  181. EnsureIn(member, dir(self), "entry not added")
  182. def read_struct(class_type, cols):
  183. """read a list of strings as the data for 'class_type'
  184. e.g. read_struct(Bus, "101 0.025 13".split())
  185. This should return a Bus with all data filled in.
  186. """
  187. EnsureEqual(len(class_type.entries), len(cols), "incomplete info. got " + str(cols))
  188. return class_type(dict(zip(class_type.entries, cols)))
  189. def TEST_struct():
  190. class Bus(struct):
  191. entries = "bus_id fail_rate repair_rate".split()
  192. types = "int real real".split()
  193. bus = read_struct(Bus, "101 0.025 13".split())
  194. # print bus.bus_id
  195. # print bus.fail_rate
  196. # print bus.repair_rate
  197. # print bus
  198. assert bus.bus_id == 101
  199. assert abs(bus.fail_rate - 0.025) < 0.0001
  200. assert abs(bus.repair_rate - 13) < 0.0001
  201. assert str(bus) == "101 0.025 13.0"
  202. # TEST_struct()
  203. #==============================================================================
  204. # round_to:
  205. #==============================================================================
  206. def round_to(val, x):
  207. """round x to the nearest `val`
  208. val must be an int"""
  209. return int(round(x / float(val)) * val)
  210. def TEST_round_to():
  211. # 10
  212. assert round_to(10, 0) == 0
  213. assert round_to(10, 1) == 0
  214. assert round_to(10, 4) == 0
  215. assert round_to(10, 5) == 10
  216. assert round_to(10, 6) == 10
  217. assert round_to(10, 10) == 10
  218. assert round_to(10, 15) == 20
  219. # 5
  220. assert round_to(5, 0) == 0
  221. assert round_to(5, 1) == 0
  222. assert round_to(5, 2.4) == 0
  223. assert round_to(5, 2.5) == 5
  224. assert round_to(5, 4) == 5
  225. assert round_to(5, 4.9) == 5
  226. assert round_to(5, 5) == 5
  227. assert round_to(5, 5.1) == 5
  228. assert round_to(5, 10) == 10
  229. # TEST_round_to()
  230. #==============================================================================
  231. # Exceptions
  232. #==============================================================================
  233. class Error(Exception):
  234. """Base class for exceptions in this module.
  235. Attributes:
  236. msg -- explanation of the error
  237. http://stackoverflow.com/questions/894088/how-do-i-get-the-current-file-current-class-and-current-method-with-python
  238. http://docs.python.org/library/sys.html
  239. http://docs.python.org/library/traceback.html
  240. http://www.doughellmann.com/PyMOTW/traceback/
  241. http://benjamin-schweizer.de/improved-python-traceback-module.html
  242. """
  243. def __init__(self, msg, use_stack_n= -1):
  244. self.msg = msg
  245. self.stack_n = use_stack_n
  246. def __str__(self):
  247. _exc_type, _exc_value, exc_traceback = sys.exc_info()
  248. stack = traceback.extract_tb(exc_traceback) # ==> [(filename, line number, function name, text)]
  249. file = os.path.basename(stack[self.stack_n][0]).split('.')[0]
  250. func = stack[self.stack_n][2]
  251. line = stack[self.stack_n][1]
  252. return "[E] Error: '%s' (%s.%s[%d])" % (self.msg, file, func, line)
  253. def Ensure(cond, msg):
  254. if not cond:
  255. raise Error(msg, -2)
  256. def EnsureEqual(first, second, msg=""):
  257. if first != second:
  258. raise Error("Expected '%s' = '%s' %s" % (str(first), str(second), msg), -2)
  259. def EnsureNotEqual(first, second, msg=""):
  260. if first == second:
  261. if str(first) == str(second):
  262. raise Error("Expected Type '%s' = '%s' on '%s' %s" % (first.__class__, second.__class__, str(first), msg), -2)
  263. raise Error("Expected '%s' = '%s' %s" % (str(first), str(second), msg), -2)
  264. def EnsureIn(first, second, msg=""):
  265. if first not in second:
  266. raise Error("Expected '%s' in '%s' %s" % (str(first), str(second), msg), -2)
  267. def TEST_EnsureEqual():
  268. def lumberjack():
  269. bright_side_of_death()
  270. def bright_side_of_death():
  271. EnsureEqual(3, 5)
  272. try:
  273. lumberjack()
  274. except Exception as exc:
  275. print exc