140 lines
4.1 KiB
Python
140 lines
4.1 KiB
Python
from kivy.tests.common import GraphicUnitTest, ensure_web_server
|
|
|
|
from kivy.uix.image import AsyncImage
|
|
from kivy.config import Config
|
|
from kivy import kivy_examples_dir
|
|
|
|
from zipfile import ZipFile
|
|
from os.path import join, dirname, abspath
|
|
from os import remove
|
|
|
|
try:
|
|
from urllib import urlretrieve
|
|
except ImportError:
|
|
from urllib.request import urlretrieve
|
|
|
|
|
|
class AsyncImageTestCase(GraphicUnitTest):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
ensure_web_server(kivy_examples_dir)
|
|
|
|
def setUp(self):
|
|
self.maxfps = Config.getint('graphics', 'maxfps')
|
|
assert(self.maxfps > 0)
|
|
super(AsyncImageTestCase, self).setUp()
|
|
|
|
def zip_frames(self, path):
|
|
with ZipFile(path) as zipf:
|
|
return len(zipf.namelist())
|
|
|
|
def load_zipimage(self, source, frames):
|
|
# keep running the test until loaded (or timeout)
|
|
maxfps = self.maxfps
|
|
timeout = 30 * maxfps
|
|
|
|
# load ZIP with images named: 000.png, 001.png, ...
|
|
image = AsyncImage(
|
|
source=source,
|
|
anim_delay=0.0333333333333333
|
|
)
|
|
image.test_loaded = False
|
|
self.render(image)
|
|
|
|
# bind to 'on_load' because there are various
|
|
# steps where the image is (re)loaded, but
|
|
# the event is triggered only at the end
|
|
image.bind(on_load=lambda *_, **__: setattr(
|
|
image, 'test_loaded', True
|
|
))
|
|
|
|
while timeout and not image.test_loaded:
|
|
self.advance_frames(1)
|
|
timeout -= 1
|
|
|
|
proxyimg = image._coreimage
|
|
self.assertTrue(proxyimg.anim_available)
|
|
self.assertEqual(len(proxyimg.image.textures), frames)
|
|
return image
|
|
|
|
def test_remote_zipsequence(self):
|
|
# cube ZIP has 63 PNGs used for animation
|
|
ZIP = (
|
|
'http://localhost:8000/widgets/'
|
|
'sequenced_images/data/images/cube.zip'
|
|
)
|
|
|
|
# ref Loader._load_urllib
|
|
tempf, headers = urlretrieve(ZIP)
|
|
ZIP_pngs = self.zip_frames(tempf)
|
|
remove(tempf)
|
|
|
|
image = self.load_zipimage(ZIP, ZIP_pngs)
|
|
# pure delay * fps isn't enough and
|
|
# just +1 isn't either (index collisions)
|
|
self.assertTrue(self.check_sequence_frames(
|
|
image._coreimage,
|
|
int(image._coreimage.anim_delay * self.maxfps + 3)
|
|
))
|
|
|
|
def test_local_zipsequence(self):
|
|
# cube ZIP has 63 PNGs used for animation
|
|
ZIP = join(
|
|
kivy_examples_dir, 'widgets', 'sequenced_images',
|
|
'data', 'images', 'cube.zip'
|
|
)
|
|
ZIP_pngs = self.zip_frames(ZIP)
|
|
|
|
image = self.load_zipimage(ZIP, ZIP_pngs)
|
|
# pure delay * fps isn't enough and
|
|
# just +1 isn't either (index collisions)
|
|
self.assertTrue(self.check_sequence_frames(
|
|
image._coreimage,
|
|
int(image._coreimage.anim_delay * self.maxfps + 3)
|
|
))
|
|
|
|
def check_sequence_frames(self, img, frames, slides=5):
|
|
# check whether it really changes the images
|
|
# in the anim_delay interval
|
|
old = None
|
|
|
|
while slides:
|
|
# different frames, sequence is changing
|
|
self.assertNotEqual(img.anim_index, old)
|
|
|
|
old = img.anim_index
|
|
self.advance_frames(
|
|
frames
|
|
)
|
|
slides -= 1
|
|
|
|
return True
|
|
|
|
def test_reload_asyncimage(self):
|
|
from kivy.resources import resource_find
|
|
from tempfile import mkdtemp
|
|
from os import remove
|
|
from shutil import copyfile, rmtree
|
|
|
|
fn = resource_find('data/logo/kivy-icon-16.png')
|
|
t = mkdtemp()
|
|
source = join(t, 'source.png')
|
|
copyfile(fn, source)
|
|
image = AsyncImage(source=source)
|
|
self.render(image, framecount=2)
|
|
self.assertEqual(image.texture_size, [16, 16])
|
|
remove(source)
|
|
|
|
fn = resource_find('data/logo/kivy-icon-32.png')
|
|
copyfile(fn, source)
|
|
image.reload()
|
|
self.render(image, framecount=2)
|
|
self.assertEqual(image.texture_size, [32, 32])
|
|
remove(source)
|
|
rmtree(t)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
import unittest
|
|
unittest.main()
|