We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Regression when upgrading from 1.0.9-stable to 1.0.10-dev?
Hello,

I just upgraded Kivy to the latest version via the "git pull" command. I was running 1.0.9 stable and updated Kivy to 1.0.10-dev.

When rerunning my program (on 1.0.9 everything works just fine), this error / stacktrace pops up: http://dpaste.com/hold/676134/.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `kivy/uix/image.py`
Content:
```
1 '''
2 Image
3 =====
4 
5 The :class:`Image` widget is used to display an image. ::
6 
7     wimg = Image(source='mylogo.png')
8 
9 Asynchronous loading
10 --------------------
11 
12 To load an image asynchronously (for example from an external webserver), use
13 the :class:`AsyncImage` subclass ::
14 
15     aimg = AsyncImage(source='http://mywebsite.com/logo.png')
16 
17 Alignement
18 ----------
19 
20 By default, the image is centered and fitted inside the widget bounding box.
21 If you don't want that, you can inherit from Image and create your own style.
22 
23 For example, if you want your image to take the same size of your widget, you
24 can do ::
25 
26     class FullImage(Image):
27         pass
28 
29 And in your kivy language file, you can do ::
30 
31     <FullImage>:
32         canvas:
33             Color:
34                 rgb: (1, 1, 1)
35             Rectangle:
36                 texture: self.texture
37                 size: self.size
38                 pos: self.pos
39 
40 '''
41 
42 __all__ = ('Image', 'AsyncImage')
43 
44 from kivy.uix.widget import Widget
45 from kivy.core.image import Image as CoreImage
46 from kivy.resources import resource_find
47 from kivy.properties import StringProperty, ObjectProperty, ListProperty, \
48         AliasProperty, BooleanProperty, NumericProperty
49 from kivy.loader import Loader
50 
51 
52 class Image(Widget):
53     '''Image class, see module documentation for more information.
54     '''
55 
56     source = StringProperty(None)
57     '''Filename / source of your image.
58 
59     :data:`source` a :class:`~kivy.properties.StringProperty`, default to None.
60     '''
61 
62     texture = ObjectProperty(None, allownone=True)
63     '''Texture object of the image.
64 
65     Depending of the texture creation, the value will be a
66     :class:`~kivy.graphics.texture.Texture` or
67     :class:`~kivy.graphics.texture.TextureRegion` object.
68 
69     :data:`texture` is a :class:`~kivy.properties.ObjectProperty`, default to
70     None.
71     '''
72 
73     texture_size = ListProperty([0, 0])
74     '''Texture size of the image.
75 
76     .. warning::
77 
78         The texture size is set after the texture property. So if you listen on
79         the change to :data:`texture`, the property texture_size will be not yet
80         updated. Use self.texture.size instead.
81     '''
82 
83     def get_image_ratio(self):
84         if self.texture:
85             return self.texture.width / float(self.texture.height)
86         return 1.
87 
88     mipmap = BooleanProperty(False)
89     '''Indicate if you want OpenGL mipmapping to be apply on the texture or not.
90     Read :ref:`mipmap` for more information.
91 
92     .. versionadded:: 1.0.7
93 
94     :data:`mipmap` is a :class:`~kivy.properties.BooleanProperty`, default to
95     False.
96     '''
97 
98     image_ratio = AliasProperty(get_image_ratio, None, bind=('texture', ))
99     '''Ratio of the image (width / float(height)
100 
101     :data:`image_ratio` is a :class:`~kivy.properties.AliasProperty`, and is
102     read-only.
103     '''
104 
105     color = ListProperty([1, 1, 1, 1])
106     '''Image color, in the format (r, g, b, a). This attribute can be used for
107     'tint' an image. Be careful, if the source image is not gray/white, the
108     color will not really work as expected.
109 
110     .. versionadded:: 1.0.6
111 
112     :data:`color` is a :class:`~kivy.properties.ListProperty`, default to [1, 1,
113     1, 1].
114     '''
115 
116     allow_stretch = BooleanProperty(False)
117     '''If True, the normalized image size will be maximized to fit in the image
118     box. Otherwise, if the box is too tall, the image will not be streched more
119     than 1:1 pixels
120 
121     .. versionadded:: 1.0.7
122 
123     :data:`allow_stretch` is a :class:`~kivy.properties.BooleanProperty`,
124     default to False
125     '''
126 
127     keep_ratio = BooleanProperty(True)
128     '''If False along with allow_stretch being True, the normalized image
129     size will be maximized to fit in the image box disregarding the aspect
130     ratio of the image.
131     Otherwise, if the box is too tall, the image will not be streched more
132     than 1:1 pixels
133 
134     .. versionadded:: 1.0.8
135 
136     :data:`keep_ratio` is a :class:`~kivy.properties.BooleanProperty`,
137     default to True
138     '''
139 
140     anim_delay = NumericProperty(.25)
141     '''Delay of animation if the image is sequenced (like animated gif).
142     If the anim_delay is set to -1, the animation will be stopped.
143 
144     .. versionadded:: 1.0.8
145 
146     :data:`anim_delay` is a :class:`~kivy.properties.NumericProperty`, default
147     to .25 (4 FPS)
148     '''
149 
150     def get_norm_image_size(self):
151         if not self.texture:
152             return self.size
153         ratio = self.image_ratio
154         w, h = self.size
155         tw, th = self.texture.size
156 
157         # ensure that the width is always maximized to the containter width
158         if self.allow_stretch:
159             if not self.keep_ratio:
160                 return w, h
161             iw = w
162         else:
163             iw = min(w, tw)
164         # calculate the appropriate height
165         ih = iw / ratio
166         # if the height is too higher, take the height of the container
167         # and calculate appropriate width. no need to test further. :)
168         if ih > h:
169             if self.allow_stretch:
170                 ih = h
171             else:
172                 ih = min(h, th)
173             iw = ih * ratio
174 
175         return iw, ih
176 
177 
178     norm_image_size = AliasProperty(get_norm_image_size, None, bind=(
179         'texture', 'size', 'image_ratio', 'allow_stretch'))
180     '''Normalized image size withing the widget box.
181 
182     This size will be always fitted to the widget size, and preserve the image
183     ratio.
184 
185     :data:`norm_image_size` is a :class:`~kivy.properties.AliasProperty`, and is
186     read-only.
187     '''
188 
189     def __init__(self, **kwargs):
190         self._coreimage = None
191         super(Image, self).__init__(**kwargs)
192         self.bind(source=self.texture_update,
193                   mipmap=self.texture_update)
194         if self.source is not None:
195             self.texture_update()
196 
197     def texture_update(self, *largs):
198         if not self.source:
199             self.texture = None
200         else:
201             filename = resource_find(self.source)
202             if filename is None:
203                 return
204             mipmap = self.mipmap
205             if self._coreimage is not None:
206                 self._coreimage.unbind(on_texture=self._on_tex_change)
207             self._coreimage = ci = CoreImage(filename, mipmap=mipmap,
208                     anim_delay=self.anim_delay)
209             ci.bind(on_texture=self._on_tex_change)
210             self.texture = ci.texture
211 
212     def on_anim_delay(self, instance, value):
213         if self._coreimage is None:
214             return
215         self._coreimage.anim_delay = value
216         if value < 0:
217             self._coreimage.anim_reset(False)
218 
219     def on_texture(self, instance, value):
220         if value is not None:
221             self.texture_size = list(value.size)
222 
223     def _on_tex_change(self, *largs):
224         # update texture from core image
225         self.texture = self._coreimage.texture
226 
227 
228 class AsyncImage(Image):
229     '''Asynchronous Image class, see module documentation for more information.
230     '''
231 
232     def __init__(self, **kwargs):
233         self._coreimage = None
234         super(AsyncImage, self).__init__(**kwargs)
235         self.unbind(source=self.texture_update,
236                     mipmap=self.texture_update)
237 
238     def on_source(self, instance, value):
239         if not value:
240             self._coreimage.unbind(on_texture=self._on_tex_change)
241             self.texture = None
242             self._coreimage = None
243         else:
244             if not self.is_uri(value):
245                 value = resource_find(value)
246             self._coreimage = image = Loader.image(value)
247             image.bind(on_load=self.on_source_load)
248             image.bind(on_texture=self._on_tex_change)
249             self.texture = image.texture
250 
251     def on_source_load(self, value):
252         image = self._coreimage.image
253         if not image:
254             return
255         self.texture = image.texture
256 
257     def is_uri(self, filename):
258         proto = filename.split('://', 1)[0]
259         return proto in ('http', 'https', 'ftp')
260 
261     def _on_tex_change(self, *largs):
262         if self._coreimage:
263             self.texture = self._coreimage.texture
264
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/kivy/uix/image.py b/kivy/uix/image.py
--- a/kivy/uix/image.py
+++ b/kivy/uix/image.py
@@ -237,7 +237,8 @@
 
     def on_source(self, instance, value):
         if not value:
-            self._coreimage.unbind(on_texture=self._on_tex_change)
+            if self._coreimage is not None:
+                self._coreimage.unbind(on_texture=self._on_tex_change)
             self.texture = None
             self._coreimage = None
         else:

{"golden_diff": "diff --git a/kivy/uix/image.py b/kivy/uix/image.py\n--- a/kivy/uix/image.py\n+++ b/kivy/uix/image.py\n@@ -237,7 +237,8 @@\n \n     def on_source(self, instance, value):\n         if not value:\n-            self._coreimage.unbind(on_texture=self._on_tex_change)\n+            if self._coreimage is not None:\n+                self._coreimage.unbind(on_texture=self._on_tex_change)\n             self.texture = None\n             self._coreimage = None\n         else:\n", "issue": "Regression when upgrading from 1.0.9-stable to 1.0.10-dev?\nHello,\n\nI just upgraded Kivy to the latest version via the \"git pull\" command. I was running 1.0.9 stable and updated Kivy to 1.0.10-dev.\n\nWhen rerunning my program (on 1.0.9 everything works just fine), this error / stacktrace pops up: http://dpaste.com/hold/676134/.\n\n", "before_files": [{"content": "'''\nImage\n=====\n\nThe :class:`Image` widget is used to display an image. ::\n\n    wimg = Image(source='mylogo.png')\n\nAsynchronous loading\n--------------------\n\nTo load an image asynchronously (for example from an external webserver), use\nthe :class:`AsyncImage` subclass ::\n\n    aimg = AsyncImage(source='http://mywebsite.com/logo.png')\n\nAlignement\n----------\n\nBy default, the image is centered and fitted inside the widget bounding box.\nIf you don't want that, you can inherit from Image and create your own style.\n\nFor example, if you want your image to take the same size of your widget, you\ncan do ::\n\n    class FullImage(Image):\n        pass\n\nAnd in your kivy language file, you can do ::\n\n    <FullImage>:\n        canvas:\n            Color:\n                rgb: (1, 1, 1)\n            Rectangle:\n                texture: self.texture\n                size: self.size\n                pos: self.pos\n\n'''\n\n__all__ = ('Image', 'AsyncImage')\n\nfrom kivy.uix.widget import Widget\nfrom kivy.core.image import Image as CoreImage\nfrom kivy.resources import resource_find\nfrom kivy.properties import StringProperty, ObjectProperty, ListProperty, \\\n        AliasProperty, BooleanProperty, NumericProperty\nfrom kivy.loader import Loader\n\n\nclass Image(Widget):\n    '''Image class, see module documentation for more information.\n    '''\n\n    source = StringProperty(None)\n    '''Filename / source of your image.\n\n    :data:`source` a :class:`~kivy.properties.StringProperty`, default to None.\n    '''\n\n    texture = ObjectProperty(None, allownone=True)\n    '''Texture object of the image.\n\n    Depending of the texture creation, the value will be a\n    :class:`~kivy.graphics.texture.Texture` or\n    :class:`~kivy.graphics.texture.TextureRegion` object.\n\n    :data:`texture` is a :class:`~kivy.properties.ObjectProperty`, default to\n    None.\n    '''\n\n    texture_size = ListProperty([0, 0])\n    '''Texture size of the image.\n\n    .. warning::\n\n        The texture size is set after the texture property. So if you listen on\n        the change to :data:`texture`, the property texture_size will be not yet\n        updated. Use self.texture.size instead.\n    '''\n\n    def get_image_ratio(self):\n        if self.texture:\n            return self.texture.width / float(self.texture.height)\n        return 1.\n\n    mipmap = BooleanProperty(False)\n    '''Indicate if you want OpenGL mipmapping to be apply on the texture or not.\n    Read :ref:`mipmap` for more information.\n\n    .. versionadded:: 1.0.7\n\n    :data:`mipmap` is a :class:`~kivy.properties.BooleanProperty`, default to\n    False.\n    '''\n\n    image_ratio = AliasProperty(get_image_ratio, None, bind=('texture', ))\n    '''Ratio of the image (width / float(height)\n\n    :data:`image_ratio` is a :class:`~kivy.properties.AliasProperty`, and is\n    read-only.\n    '''\n\n    color = ListProperty([1, 1, 1, 1])\n    '''Image color, in the format (r, g, b, a). This attribute can be used for\n    'tint' an image. Be careful, if the source image is not gray/white, the\n    color will not really work as expected.\n\n    .. versionadded:: 1.0.6\n\n    :data:`color` is a :class:`~kivy.properties.ListProperty`, default to [1, 1,\n    1, 1].\n    '''\n\n    allow_stretch = BooleanProperty(False)\n    '''If True, the normalized image size will be maximized to fit in the image\n    box. Otherwise, if the box is too tall, the image will not be streched more\n    than 1:1 pixels\n\n    .. versionadded:: 1.0.7\n\n    :data:`allow_stretch` is a :class:`~kivy.properties.BooleanProperty`,\n    default to False\n    '''\n\n    keep_ratio = BooleanProperty(True)\n    '''If False along with allow_stretch being True, the normalized image\n    size will be maximized to fit in the image box disregarding the aspect\n    ratio of the image.\n    Otherwise, if the box is too tall, the image will not be streched more\n    than 1:1 pixels\n\n    .. versionadded:: 1.0.8\n\n    :data:`keep_ratio` is a :class:`~kivy.properties.BooleanProperty`,\n    default to True\n    '''\n\n    anim_delay = NumericProperty(.25)\n    '''Delay of animation if the image is sequenced (like animated gif).\n    If the anim_delay is set to -1, the animation will be stopped.\n\n    .. versionadded:: 1.0.8\n\n    :data:`anim_delay` is a :class:`~kivy.properties.NumericProperty`, default\n    to .25 (4 FPS)\n    '''\n\n    def get_norm_image_size(self):\n        if not self.texture:\n            return self.size\n        ratio = self.image_ratio\n        w, h = self.size\n        tw, th = self.texture.size\n\n        # ensure that the width is always maximized to the containter width\n        if self.allow_stretch:\n            if not self.keep_ratio:\n                return w, h\n            iw = w\n        else:\n            iw = min(w, tw)\n        # calculate the appropriate height\n        ih = iw / ratio\n        # if the height is too higher, take the height of the container\n        # and calculate appropriate width. no need to test further. :)\n        if ih > h:\n            if self.allow_stretch:\n                ih = h\n            else:\n                ih = min(h, th)\n            iw = ih * ratio\n\n        return iw, ih\n\n\n    norm_image_size = AliasProperty(get_norm_image_size, None, bind=(\n        'texture', 'size', 'image_ratio', 'allow_stretch'))\n    '''Normalized image size withing the widget box.\n\n    This size will be always fitted to the widget size, and preserve the image\n    ratio.\n\n    :data:`norm_image_size` is a :class:`~kivy.properties.AliasProperty`, and is\n    read-only.\n    '''\n\n    def __init__(self, **kwargs):\n        self._coreimage = None\n        super(Image, self).__init__(**kwargs)\n        self.bind(source=self.texture_update,\n                  mipmap=self.texture_update)\n        if self.source is not None:\n            self.texture_update()\n\n    def texture_update(self, *largs):\n        if not self.source:\n            self.texture = None\n        else:\n            filename = resource_find(self.source)\n            if filename is None:\n                return\n            mipmap = self.mipmap\n            if self._coreimage is not None:\n                self._coreimage.unbind(on_texture=self._on_tex_change)\n            self._coreimage = ci = CoreImage(filename, mipmap=mipmap,\n                    anim_delay=self.anim_delay)\n            ci.bind(on_texture=self._on_tex_change)\n            self.texture = ci.texture\n\n    def on_anim_delay(self, instance, value):\n        if self._coreimage is None:\n            return\n        self._coreimage.anim_delay = value\n        if value < 0:\n            self._coreimage.anim_reset(False)\n\n    def on_texture(self, instance, value):\n        if value is not None:\n            self.texture_size = list(value.size)\n\n    def _on_tex_change(self, *largs):\n        # update texture from core image\n        self.texture = self._coreimage.texture\n\n\nclass AsyncImage(Image):\n    '''Asynchronous Image class, see module documentation for more information.\n    '''\n\n    def __init__(self, **kwargs):\n        self._coreimage = None\n        super(AsyncImage, self).__init__(**kwargs)\n        self.unbind(source=self.texture_update,\n                    mipmap=self.texture_update)\n\n    def on_source(self, instance, value):\n        if not value:\n            self._coreimage.unbind(on_texture=self._on_tex_change)\n            self.texture = None\n            self._coreimage = None\n        else:\n            if not self.is_uri(value):\n                value = resource_find(value)\n            self._coreimage = image = Loader.image(value)\n            image.bind(on_load=self.on_source_load)\n            image.bind(on_texture=self._on_tex_change)\n            self.texture = image.texture\n\n    def on_source_load(self, value):\n        image = self._coreimage.image\n        if not image:\n            return\n        self.texture = image.texture\n\n    def is_uri(self, filename):\n        proto = filename.split('://', 1)[0]\n        return proto in ('http', 'https', 'ftp')\n\n    def _on_tex_change(self, *largs):\n        if self._coreimage:\n            self.texture = self._coreimage.texture\n", "path": "kivy/uix/image.py"}], "after_files": [{"content": "'''\nImage\n=====\n\nThe :class:`Image` widget is used to display an image. ::\n\n    wimg = Image(source='mylogo.png')\n\nAsynchronous loading\n--------------------\n\nTo load an image asynchronously (for example from an external webserver), use\nthe :class:`AsyncImage` subclass ::\n\n    aimg = AsyncImage(source='http://mywebsite.com/logo.png')\n\nAlignement\n----------\n\nBy default, the image is centered and fitted inside the widget bounding box.\nIf you don't want that, you can inherit from Image and create your own style.\n\nFor example, if you want your image to take the same size of your widget, you\ncan do ::\n\n    class FullImage(Image):\n        pass\n\nAnd in your kivy language file, you can do ::\n\n    <FullImage>:\n        canvas:\n            Color:\n                rgb: (1, 1, 1)\n            Rectangle:\n                texture: self.texture\n                size: self.size\n                pos: self.pos\n\n'''\n\n__all__ = ('Image', 'AsyncImage')\n\nfrom kivy.uix.widget import Widget\nfrom kivy.core.image import Image as CoreImage\nfrom kivy.resources import resource_find\nfrom kivy.properties import StringProperty, ObjectProperty, ListProperty, \\\n        AliasProperty, BooleanProperty, NumericProperty\nfrom kivy.loader import Loader\n\n\nclass Image(Widget):\n    '''Image class, see module documentation for more information.\n    '''\n\n    source = StringProperty(None)\n    '''Filename / source of your image.\n\n    :data:`source` a :class:`~kivy.properties.StringProperty`, default to None.\n    '''\n\n    texture = ObjectProperty(None, allownone=True)\n    '''Texture object of the image.\n\n    Depending of the texture creation, the value will be a\n    :class:`~kivy.graphics.texture.Texture` or\n    :class:`~kivy.graphics.texture.TextureRegion` object.\n\n    :data:`texture` is a :class:`~kivy.properties.ObjectProperty`, default to\n    None.\n    '''\n\n    texture_size = ListProperty([0, 0])\n    '''Texture size of the image.\n\n    .. warning::\n\n        The texture size is set after the texture property. So if you listen on\n        the change to :data:`texture`, the property texture_size will be not yet\n        updated. Use self.texture.size instead.\n    '''\n\n    def get_image_ratio(self):\n        if self.texture:\n            return self.texture.width / float(self.texture.height)\n        return 1.\n\n    mipmap = BooleanProperty(False)\n    '''Indicate if you want OpenGL mipmapping to be apply on the texture or not.\n    Read :ref:`mipmap` for more information.\n\n    .. versionadded:: 1.0.7\n\n    :data:`mipmap` is a :class:`~kivy.properties.BooleanProperty`, default to\n    False.\n    '''\n\n    image_ratio = AliasProperty(get_image_ratio, None, bind=('texture', ))\n    '''Ratio of the image (width / float(height)\n\n    :data:`image_ratio` is a :class:`~kivy.properties.AliasProperty`, and is\n    read-only.\n    '''\n\n    color = ListProperty([1, 1, 1, 1])\n    '''Image color, in the format (r, g, b, a). This attribute can be used for\n    'tint' an image. Be careful, if the source image is not gray/white, the\n    color will not really work as expected.\n\n    .. versionadded:: 1.0.6\n\n    :data:`color` is a :class:`~kivy.properties.ListProperty`, default to [1, 1,\n    1, 1].\n    '''\n\n    allow_stretch = BooleanProperty(False)\n    '''If True, the normalized image size will be maximized to fit in the image\n    box. Otherwise, if the box is too tall, the image will not be streched more\n    than 1:1 pixels\n\n    .. versionadded:: 1.0.7\n\n    :data:`allow_stretch` is a :class:`~kivy.properties.BooleanProperty`,\n    default to False\n    '''\n\n    keep_ratio = BooleanProperty(True)\n    '''If False along with allow_stretch being True, the normalized image\n    size will be maximized to fit in the image box disregarding the aspect\n    ratio of the image.\n    Otherwise, if the box is too tall, the image will not be streched more\n    than 1:1 pixels\n\n    .. versionadded:: 1.0.8\n\n    :data:`keep_ratio` is a :class:`~kivy.properties.BooleanProperty`,\n    default to True\n    '''\n\n    anim_delay = NumericProperty(.25)\n    '''Delay of animation if the image is sequenced (like animated gif).\n    If the anim_delay is set to -1, the animation will be stopped.\n\n    .. versionadded:: 1.0.8\n\n    :data:`anim_delay` is a :class:`~kivy.properties.NumericProperty`, default\n    to .25 (4 FPS)\n    '''\n\n    def get_norm_image_size(self):\n        if not self.texture:\n            return self.size\n        ratio = self.image_ratio\n        w, h = self.size\n        tw, th = self.texture.size\n\n        # ensure that the width is always maximized to the containter width\n        if self.allow_stretch:\n            if not self.keep_ratio:\n                return w, h\n            iw = w\n        else:\n            iw = min(w, tw)\n        # calculate the appropriate height\n        ih = iw / ratio\n        # if the height is too higher, take the height of the container\n        # and calculate appropriate width. no need to test further. :)\n        if ih > h:\n            if self.allow_stretch:\n                ih = h\n            else:\n                ih = min(h, th)\n            iw = ih * ratio\n\n        return iw, ih\n\n\n    norm_image_size = AliasProperty(get_norm_image_size, None, bind=(\n        'texture', 'size', 'image_ratio', 'allow_stretch'))\n    '''Normalized image size withing the widget box.\n\n    This size will be always fitted to the widget size, and preserve the image\n    ratio.\n\n    :data:`norm_image_size` is a :class:`~kivy.properties.AliasProperty`, and is\n    read-only.\n    '''\n\n    def __init__(self, **kwargs):\n        self._coreimage = None\n        super(Image, self).__init__(**kwargs)\n        self.bind(source=self.texture_update,\n                  mipmap=self.texture_update)\n        if self.source is not None:\n            self.texture_update()\n\n    def texture_update(self, *largs):\n        if not self.source:\n            self.texture = None\n        else:\n            filename = resource_find(self.source)\n            if filename is None:\n                return\n            mipmap = self.mipmap\n            if self._coreimage is not None:\n                self._coreimage.unbind(on_texture=self._on_tex_change)\n            self._coreimage = ci = CoreImage(filename, mipmap=mipmap,\n                    anim_delay=self.anim_delay)\n            ci.bind(on_texture=self._on_tex_change)\n            self.texture = ci.texture\n\n    def on_anim_delay(self, instance, value):\n        if self._coreimage is None:\n            return\n        self._coreimage.anim_delay = value\n        if value < 0:\n            self._coreimage.anim_reset(False)\n\n    def on_texture(self, instance, value):\n        if value is not None:\n            self.texture_size = list(value.size)\n\n    def _on_tex_change(self, *largs):\n        # update texture from core image\n        self.texture = self._coreimage.texture\n\n\nclass AsyncImage(Image):\n    '''Asynchronous Image class, see module documentation for more information.\n    '''\n\n    def __init__(self, **kwargs):\n        self._coreimage = None\n        super(AsyncImage, self).__init__(**kwargs)\n        self.unbind(source=self.texture_update,\n                    mipmap=self.texture_update)\n\n    def on_source(self, instance, value):\n        if not value:\n            if self._coreimage is not None:\n                self._coreimage.unbind(on_texture=self._on_tex_change)\n            self.texture = None\n            self._coreimage = None\n        else:\n            if not self.is_uri(value):\n                value = resource_find(value)\n            self._coreimage = image = Loader.image(value)\n            image.bind(on_load=self.on_source_load)\n            image.bind(on_texture=self._on_tex_change)\n            self.texture = image.texture\n\n    def on_source_load(self, value):\n        image = self._coreimage.image\n        if not image:\n            return\n        self.texture = image.texture\n\n    def is_uri(self, filename):\n        proto = filename.split('://', 1)[0]\n        return proto in ('http', 'https', 'ftp')\n\n    def _on_tex_change(self, *largs):\n        if self._coreimage:\n            self.texture = self._coreimage.texture\n", "path": "kivy/uix/image.py"}]}