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