1from __future__ import division
2
3from unittest import TestCase as _Base
4import datetime
5import errno
6import functools
7import os
8import sys
9import types
10
11from av.datasets import fate as fate_suite
12
13
14try:
15    import PIL.Image as Image
16    import PIL.ImageFilter as ImageFilter
17except ImportError:
18    Image = ImageFilter = None
19
20
21is_windows = os.name == 'nt'
22skip_tests = frozenset(os.environ.get("PYAV_SKIP_TESTS", "").split(","))
23
24
25def makedirs(path):
26    try:
27        os.makedirs(path)
28    except OSError as e:
29        if e.errno != errno.EEXIST:
30            raise
31
32
33_start_time = datetime.datetime.now()
34
35
36def _sandbox(timed=False):
37    root = os.path.abspath(os.path.join(
38        __file__, '..', '..',
39        'sandbox'
40    ))
41
42    sandbox = os.path.join(
43        root,
44        _start_time.strftime('%Y%m%d-%H%M%S'),
45    ) if timed else root
46    if not os.path.exists(sandbox):
47        os.makedirs(sandbox)
48    return sandbox
49
50
51def asset(*args):
52    adir = os.path.dirname(__file__)
53    return os.path.abspath(os.path.join(adir, 'assets', *args))
54
55
56# Store all of the sample data here.
57os.environ['PYAV_TESTDATA_DIR'] = asset()
58
59
60def fate_png():
61    return fate_suite('png1/55c99e750a5fd6_50314226.png')
62
63
64def sandboxed(*args, **kwargs):
65    do_makedirs = kwargs.pop('makedirs', True)
66    base = kwargs.pop('sandbox', None)
67    timed = kwargs.pop('timed', False)
68    if kwargs:
69        raise TypeError('extra kwargs: %s' % ', '.join(sorted(kwargs)))
70    path = os.path.join(_sandbox(timed=timed) if base is None else base, *args)
71    if do_makedirs:
72        makedirs(os.path.dirname(path))
73    return path
74
75
76class MethodLogger(object):
77
78    def __init__(self, obj):
79        self._obj = obj
80        self._log = []
81
82    def __getattr__(self, name):
83        value = getattr(self._obj, name)
84        if isinstance(value, (types.MethodType, types.FunctionType, types.BuiltinFunctionType, types.BuiltinMethodType)):
85            return functools.partial(self._method, name, value)
86        else:
87            self._log.append(('__getattr__', (name, ), {}))
88            return value
89
90    def _method(self, name, meth, *args, **kwargs):
91        self._log.append((name, args, kwargs))
92        return meth(*args, **kwargs)
93
94    def _filter(self, type_):
95        return [log for log in self._log if log[0] == type_]
96
97
98class TestCase(_Base):
99
100    @classmethod
101    def _sandbox(cls, timed=True):
102        path = os.path.join(_sandbox(timed=timed), cls.__name__)
103        makedirs(path)
104        return path
105
106    @property
107    def sandbox(self):
108        return self._sandbox(timed=True)
109
110    def sandboxed(self, *args, **kwargs):
111        kwargs.setdefault('sandbox', self.sandbox)
112        kwargs.setdefault('timed', True)
113        return sandboxed(*args, **kwargs)
114
115    def assertImagesAlmostEqual(self, a, b, epsilon=0.1, *args):
116        self.assertEqual(a.size, b.size, 'sizes dont match')
117        a = a.filter(ImageFilter.BLUR).getdata()
118        b = b.filter(ImageFilter.BLUR).getdata()
119        for i, ax, bx in zip(range(len(a)), a, b):
120            diff = sum(abs(ac / 256 - bc / 256) for ac, bc in zip(ax, bx)) / 3
121            if diff > epsilon:
122                self.fail('images differed by %s at index %d; %s %s' % (diff, i, ax, bx))
123
124    # Add some of the unittest methods that we love from 2.7.
125    if sys.version_info < (2, 7):
126
127        def assertIs(self, a, b, msg=None):
128            if a is not b:
129                self.fail(msg or '%r at 0x%x is not %r at 0x%x; %r is not %r' % (type(a), id(a), type(b), id(b), a, b))
130
131        def assertIsNot(self, a, b, msg=None):
132            if a is b:
133                self.fail(msg or 'both are %r at 0x%x; %r' % (type(a), id(a), a))
134
135        def assertIsNone(self, x, msg=None):
136            if x is not None:
137                self.fail(msg or 'is not None; %r' % x)
138
139        def assertIsNotNone(self, x, msg=None):
140            if x is None:
141                self.fail(msg or 'is None; %r' % x)
142
143        def assertIn(self, a, b, msg=None):
144            if a not in b:
145                self.fail(msg or '%r not in %r' % (a, b))
146
147        def assertNotIn(self, a, b, msg=None):
148            if a in b:
149                self.fail(msg or '%r in %r' % (a, b))
150
151        def assertIsInstance(self, instance, types, msg=None):
152            if not isinstance(instance, types):
153                self.fail(msg or 'not an instance of %r; %r' % (types, instance))
154
155        def assertNotIsInstance(self, instance, types, msg=None):
156            if isinstance(instance, types):
157                self.fail(msg or 'is an instance of %r; %r' % (types, instance))
158