1#################################### IMPORTS ################################### 2 3is_pygame_pkg = __name__.startswith("pygame.tests.") 4 5import tempfile, sys, pygame, time, os 6 7################################################################################ 8# Python 3.x compatibility 9try: 10 xrange_ = xrange 11except NameError: 12 xrange_ = range 13 14try: 15 raw_input_ = raw_input 16except NameError: 17 raw_input_ = input 18 19 20if sys.version_info[0] == 3: 21 22 def tostring(row): 23 """Convert row of bytes to string. Expects `row` to be an 24 ``array``. 25 """ 26 return row.tobytes() 27 28else: 29 30 def tostring(row): 31 """Convert row of bytes to string. Expects `row` to be an 32 ``array``. 33 """ 34 return row.tostring() 35 36 import unittest 37 38 if not hasattr(unittest.TestCase, "subTest"): 39 import contextlib 40 41 @contextlib.contextmanager 42 def subTest(self, msg=None, **params): 43 yield 44 return 45 46 unittest.TestCase.subTest = subTest 47 48 49def geterror(): 50 return sys.exc_info()[1] 51 52 53class AssertRaisesRegexMixin(object): 54 """Provides a way to prevent DeprecationWarnings in python >= 3.2. 55 56 For this mixin to override correctly it needs to be before the 57 unittest.TestCase in the multiple inheritance hierarchy. 58 e.g. class TestClass(AssertRaisesRegexMixin, unittest.TestCase) 59 60 This class/mixin and its usage can be removed when pygame no longer 61 supports python < 3.2. 62 """ 63 64 def assertRaisesRegex(self, *args, **kwargs): 65 try: 66 return super(AssertRaisesRegexMixin, self).assertRaisesRegex( 67 *args, **kwargs 68 ) 69 except AttributeError: 70 try: 71 return super(AssertRaisesRegexMixin, self).assertRaisesRegexp( 72 *args, **kwargs 73 ) 74 except AttributeError: 75 self.skipTest("No assertRaisesRegex/assertRaisesRegexp method") 76 77 78################################################################################ 79 80this_dir = os.path.dirname(os.path.abspath(__file__)) 81trunk_dir = os.path.split(os.path.split(this_dir)[0])[0] 82if is_pygame_pkg: 83 test_module = "tests" 84else: 85 test_module = "test" 86 87 88def trunk_relative_path(relative): 89 return os.path.normpath(os.path.join(trunk_dir, relative)) 90 91 92def fixture_path(path): 93 return trunk_relative_path(os.path.join(test_module, "fixtures", path)) 94 95 96def example_path(path): 97 return trunk_relative_path(os.path.join("examples", path)) 98 99 100sys.path.insert(0, trunk_relative_path(".")) 101 102 103################################## TEMP FILES ################################## 104 105 106def get_tmp_dir(): 107 return tempfile.mkdtemp() 108 109 110################################################################################ 111 112 113def question(q): 114 return raw_input_("\n%s (y/n): " % q.rstrip(" ")).lower().strip() == "y" 115 116 117def prompt(p): 118 return raw_input_("\n%s (press enter to continue): " % p.rstrip(" ")) 119 120 121#################################### HELPERS ################################### 122 123 124def rgba_between(value, minimum=0, maximum=255): 125 if value < minimum: 126 return minimum 127 elif value > maximum: 128 return maximum 129 else: 130 return value 131 132 133def combinations(seqs): 134 """ 135 136 Recipe 496807 from ActiveState Python CookBook 137 138 Non recursive technique for getting all possible combinations of a sequence 139 of sequences. 140 141 """ 142 143 r = [[]] 144 for x in seqs: 145 r = [i + [y] for y in x for i in r] 146 return r 147 148 149def gradient(width, height): 150 """ 151 152 Yields a pt and corresponding RGBA tuple, for every (width, height) combo. 153 Useful for generating gradients. 154 155 Actual gradient may be changed, no tests rely on specific values. 156 157 Used in transform.rotate lossless tests to generate a fixture. 158 159 """ 160 161 for l in xrange_(width): 162 for t in xrange_(height): 163 yield (l, t), tuple(map(rgba_between, (l, t, l, l + t))) 164 165 166def rect_area_pts(rect): 167 for l in xrange_(rect.left, rect.right): 168 for t in xrange_(rect.top, rect.bottom): 169 yield l, t 170 171 172def rect_perimeter_pts(rect): 173 """ 174 175 Returns pts ((L, T) tuples) encompassing the perimeter of a rect. 176 177 The order is clockwise: 178 179 topleft to topright 180 topright to bottomright 181 bottomright to bottomleft 182 bottomleft to topleft 183 184 Duplicate pts are not returned 185 186 """ 187 clock_wise_from_top_left = ( 188 [(l, rect.top) for l in xrange_(rect.left, rect.right)], 189 [(rect.right - 1, t) for t in xrange_(rect.top + 1, rect.bottom)], 190 [(l, rect.bottom - 1) for l in xrange_(rect.right - 2, rect.left - 1, -1)], 191 [(rect.left, t) for t in xrange_(rect.bottom - 2, rect.top, -1)], 192 ) 193 194 for line in clock_wise_from_top_left: 195 for pt in line: 196 yield pt 197 198 199def rect_outer_bounds(rect): 200 """ 201 202 Returns topleft outerbound if possible and then the other pts, that are 203 "exclusive" bounds of the rect 204 205 ?------O 206 |RECT| ?|0)uterbound 207 |----| 208 O O 209 210 """ 211 return ([(rect.left - 1, rect.top)] if rect.left else []) + [ 212 rect.topright, 213 rect.bottomleft, 214 rect.bottomright, 215 ] 216 217 218def import_submodule(module): 219 m = __import__(module) 220 for n in module.split(".")[1:]: 221 m = getattr(m, n) 222 return m 223 224 225class SurfaceSubclass(pygame.Surface): 226 """A subclassed Surface to test inheritance.""" 227 228 def __init__(self, *args, **kwargs): 229 super(SurfaceSubclass, self).__init__(*args, **kwargs) 230 self.test_attribute = True 231 232 233def test(): 234 """ 235 236 Lightweight test for helpers 237 238 """ 239 240 r = pygame.Rect(0, 0, 10, 10) 241 assert rect_outer_bounds(r) == [(10, 0), (0, 10), (10, 10)] # tr # bl # br 242 243 assert len(list(rect_area_pts(r))) == 100 244 245 r = pygame.Rect(0, 0, 3, 3) 246 assert list(rect_perimeter_pts(r)) == [ 247 (0, 0), 248 (1, 0), 249 (2, 0), # tl -> tr 250 (2, 1), 251 (2, 2), # tr -> br 252 (1, 2), 253 (0, 2), # br -> bl 254 (0, 1), # bl -> tl 255 ] 256 257 print("Tests: OK") 258 259 260################################################################################ 261