We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Crash using weakmethod with python3
It just happen to me once, not currently reproducible, with python3:

```
   File "/home/tito/code/kivy/kivy/app.py", line 600, in run
     runTouchApp()
   File "/home/tito/code/kivy/kivy/base.py", line 454, in runTouchApp
     EventLoop.window.mainloop()
   File "/home/tito/code/kivy/kivy/core/window/window_pygame.py", line 329, in mainloop
     self._mainloop()
   File "/home/tito/code/kivy/kivy/core/window/window_pygame.py", line 235, in _mainloop
     EventLoop.idle()
   File "/home/tito/code/kivy/kivy/base.py", line 294, in idle
     Clock.tick()
   File "/home/tito/code/kivy/kivy/clock.py", line 370, in tick
     self._process_events()
   File "/home/tito/code/kivy/kivy/clock.py", line 481, in _process_events
     if event.tick(self._last_tick) is False:
   File "/home/tito/code/kivy/kivy/clock.py", line 280, in tick
     ret = callback(self._dt)
   File "/home/tito/code/kivy/kivy/animation.py", line 289, in _update
     self.dispatch('on_progress', widget, progress)
   File "_event.pyx", line 272, in kivy._event.EventDispatcher.dispatch (kivy/_event.c:3992)
   File "/home/tito/code/kivy/kivy/weakmethod.py", line 42, in __call__
     if self.proxy:
 ReferenceError: weakly-referenced object no longer exists
```


--- 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/weakmethod.py`
Content:
```
1 '''
2 Weak Method
3 ===========
4 
5 The :class:`WeakMethod` is used in the Clock class to allow a reference
6 to a bound method that permits the associated object to be garbage collected.
7 Check examples/core/clock_method.py for more information.
8 
9 This WeakMethod class is taken from the recipe
10 http://code.activestate.com/recipes/81253/, based on the nicodemus version.
11 (thanks to him !)
12 '''
13 
14 import weakref
15 import sys
16 
17 if sys.version > '3':
18 
19     class WeakMethod:
20         '''Implementation of a
21         `weakref <http://en.wikipedia.org/wiki/Weak_reference>`_
22         for functions and bound methods.
23         '''
24         def __init__(self, method):
25             self.method = None
26             self.method_name = None
27             try:
28                 if method.__self__ is not None:
29                     self.method_name = method.__func__.__name__
30                     self.proxy = weakref.proxy(method.__self__)
31                 else:
32                     self.method = method
33                     self.proxy = None
34             except AttributeError:
35                 self.method = method
36                 self.proxy = None
37 
38         def __call__(self):
39             '''Return a new bound-method like the original, or the
40             original function if it was just a function or unbound
41             method.
42             Returns None if the original object doesn't exist.
43             '''
44             if self.proxy:
45                 return getattr(self.proxy, self.method_name)
46             return self.method
47 
48         def is_dead(self):
49             '''Returns True if the referenced callable was a bound method and
50             the instance no longer exists. Otherwise, return False.
51             '''
52             return self.proxy is not None and not bool(dir(self.proxy))
53 
54         def __repr__(self):
55             return '<WeakMethod proxy={} method={} method_name={}>'.format(
56                     self.proxy, self.method, self.method_name)
57 
58 else:
59 
60     import new
61 
62     class WeakMethod(object):
63         '''Implementation of a
64         `weakref <http://en.wikipedia.org/wiki/Weak_reference>`_
65         for functions and bound methods.
66         '''
67 
68         def __init__(self, method):
69             try:
70                 if method.__self__ is not None:
71                     # bound method
72                     self._obj = weakref.ref(method.im_self)
73                 else:
74                     # unbound method
75                     self._obj = None
76                 self._func = method.im_func
77                 self._class = method.im_class
78             except AttributeError:
79                 # not a method
80                 self._obj = None
81                 self._func = method
82                 self._class = None
83 
84         def __call__(self):
85             '''Return a new bound-method like the original, or the
86             original function if it was just a function or unbound
87             method.
88             Returns None if the original object doesn't exist.
89             '''
90             if self.is_dead():
91                 return None
92             if self._obj is not None:
93                 return new.instancemethod(self._func, self._obj(), self._class)
94             else:
95                 # we don't have an instance: return just the function
96                 return self._func
97 
98         def is_dead(self):
99             '''Returns True if the referenced callable was a bound method and
100             the instance no longer exists. Otherwise, return False.
101             '''
102             return self._obj is not None and self._obj() is None
103 
104         def __eq__(self, other):
105             try:
106                 return type(self) is type(other) and self() == other()
107             except:
108                 return False
109 
110         def __ne__(self, other):
111             return not self == other
112 
113
```

Path: `kivy/factory.py`
Content:
```
1 '''
2 Factory object
3 ==============
4 
5 The factory can be used to automatically register any class or module
6 and instantiate classes from it anywhere in your project. It is an
7 implementation of the
8 `Factory Pattern <http://en.wikipedia.org/wiki/Factory_pattern>`_.
9 
10 The class list and available modules are automatically generated by setup.py.
11 
12 Example for registering a class/module::
13 
14     >>> from kivy.factory import Factory
15     >>> Factory.register('Widget', module='kivy.uix.widget')
16     >>> Factory.register('Vector', module='kivy.vector')
17 
18 Example of using the Factory::
19 
20     >>> from kivy.factory import Factory
21     >>> widget = Factory.Widget(pos=(456,456))
22     >>> vector = Factory.Vector(9, 2)
23 
24 Example using a class name::
25 
26     >>> from kivy.factory import Factory
27     >>> Factory.register('MyWidget', cls=MyWidget)
28 
29 By default, the first classname you register via the factory is permanent.
30 If you wish to change the registered class, you need to unregister the classname
31 before you re-assign it::
32 
33     >>> from kivy.factory import Factory
34     >>> Factory.register('MyWidget', cls=MyWidget)
35     >>> widget = Factory.MyWidget()
36     >>> Factory.unregister('MyWidget')
37     >>> Factory.register('MyWidget', cls=CustomWidget)
38     >>> customWidget = Factory.MyWidget()
39 '''
40 
41 __all__ = ('Factory', 'FactoryException')
42 
43 from kivy.logger import Logger
44 
45 
46 class FactoryException(Exception):
47     pass
48 
49 
50 class FactoryBase(object):
51 
52     def __init__(self):
53         super(FactoryBase, self).__init__()
54         self.classes = {}
55 
56     def is_template(self, classname):
57         '''Return True if the classname is a template from the
58         :class:`~kivy.lang.Builder`.
59 
60         .. versionadded:: 1.0.5
61         '''
62         if classname in self.classes:
63             return self.classes[classname]['is_template']
64         else:
65             return False
66 
67     def register(self, classname, cls=None, module=None, is_template=False,
68             baseclasses=None, filename=None):
69         '''Register a new classname referring to a real class or
70         class definition in a module.
71 
72         .. versionchanged:: 1.7.0
73             :data:`baseclasses` and :data:`filename` added
74 
75         .. versionchanged:: 1.0.5
76             :data:`is_template` has been added in 1.0.5.
77         '''
78         if cls is None and module is None and baseclasses is None:
79             raise ValueError(
80                 'You must specify either cls= or module= or baseclasses =')
81         if classname in self.classes:
82             return
83         self.classes[classname] = {
84             'module': module,
85             'cls': cls,
86             'is_template': is_template,
87             'baseclasses': baseclasses,
88             'filename': filename}
89 
90     def unregister(self, *classnames):
91         '''Unregisters the classnames previously registered via the
92         register method. This allows the same classnames to be re-used in
93         different contexts.
94 
95         .. versionadded:: 1.7.1
96         '''
97         for classname in classnames:
98             if classname in self.classes:
99                 self.classes.pop(classname)
100 
101     def unregister_from_filename(self, filename):
102         '''Unregister all the factory objects related to the filename passed in
103         the parameter.
104 
105         .. versionadded:: 1.7.0
106         '''
107         to_remove = [x for x in self.classes
108                 if self.classes[x]['filename'] == filename]
109         for name in to_remove:
110             del self.classes[name]
111 
112     def __getattr__(self, name):
113         classes = self.classes
114         if name not in classes:
115             raise FactoryException('Unknown class <%s>' % name)
116 
117         item = classes[name]
118         cls = item['cls']
119 
120         # No class to return, import the module
121         if cls is None:
122             if item['module']:
123                 module = __import__(name=item['module'], fromlist='.')
124                 if not hasattr(module, name):
125                     raise FactoryException(
126                         'No class named <%s> in module <%s>' % (
127                         name, item['module']))
128                 cls = item['cls'] = getattr(module, name)
129 
130             elif item['baseclasses']:
131                 rootwidgets = []
132                 for basecls in item['baseclasses'].split('+'):
133                     rootwidgets.append(Factory.get(basecls))
134                 cls = item['cls'] = type(name, tuple(rootwidgets), {})
135 
136             else:
137                 raise FactoryException('No information to create the class')
138 
139         return cls
140 
141     get = __getattr__
142 
143 
144 #: Factory instance to use for getting new classes
145 Factory = FactoryBase()
146 
147 # Now import the file with all registers
148 # automatically generated by build_factory
149 import kivy.factory_registers
150 Logger.info('Factory: %d symbols loaded' % len(Factory.classes))
151 
152 if __name__ == '__main__':
153     Factory.register('Vector', module='kivy.vector')
154     Factory.register('Widget', module='kivy.uix.widget')
155 
156
```
--- 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/factory.py b/kivy/factory.py
--- a/kivy/factory.py
+++ b/kivy/factory.py
@@ -112,6 +112,10 @@
     def __getattr__(self, name):
         classes = self.classes
         if name not in classes:
+            if name[0] == name[0].lower():
+                # if trying to access attributes like checking for `bind`
+                # then raise AttributeError
+                raise AttributeError
             raise FactoryException('Unknown class <%s>' % name)
 
         item = classes[name]
diff --git a/kivy/weakmethod.py b/kivy/weakmethod.py
--- a/kivy/weakmethod.py
+++ b/kivy/weakmethod.py
@@ -41,8 +41,11 @@
             method.
             Returns None if the original object doesn't exist.
             '''
-            if self.proxy:
-                return getattr(self.proxy, self.method_name)
+            try:
+                if self.proxy:
+                    return getattr(self.proxy, self.method_name)
+            except ReferenceError:
+                pass
             return self.method
 
         def is_dead(self):

{"golden_diff": "diff --git a/kivy/factory.py b/kivy/factory.py\n--- a/kivy/factory.py\n+++ b/kivy/factory.py\n@@ -112,6 +112,10 @@\n     def __getattr__(self, name):\n         classes = self.classes\n         if name not in classes:\n+            if name[0] == name[0].lower():\n+                # if trying to access attributes like checking for `bind`\n+                # then raise AttributeError\n+                raise AttributeError\n             raise FactoryException('Unknown class <%s>' % name)\n \n         item = classes[name]\ndiff --git a/kivy/weakmethod.py b/kivy/weakmethod.py\n--- a/kivy/weakmethod.py\n+++ b/kivy/weakmethod.py\n@@ -41,8 +41,11 @@\n             method.\n             Returns None if the original object doesn't exist.\n             '''\n-            if self.proxy:\n-                return getattr(self.proxy, self.method_name)\n+            try:\n+                if self.proxy:\n+                    return getattr(self.proxy, self.method_name)\n+            except ReferenceError:\n+                pass\n             return self.method\n \n         def is_dead(self):\n", "issue": "Crash using weakmethod with python3\nIt just happen to me once, not currently reproducible, with python3:\n\n```\n   File \"/home/tito/code/kivy/kivy/app.py\", line 600, in run\n     runTouchApp()\n   File \"/home/tito/code/kivy/kivy/base.py\", line 454, in runTouchApp\n     EventLoop.window.mainloop()\n   File \"/home/tito/code/kivy/kivy/core/window/window_pygame.py\", line 329, in mainloop\n     self._mainloop()\n   File \"/home/tito/code/kivy/kivy/core/window/window_pygame.py\", line 235, in _mainloop\n     EventLoop.idle()\n   File \"/home/tito/code/kivy/kivy/base.py\", line 294, in idle\n     Clock.tick()\n   File \"/home/tito/code/kivy/kivy/clock.py\", line 370, in tick\n     self._process_events()\n   File \"/home/tito/code/kivy/kivy/clock.py\", line 481, in _process_events\n     if event.tick(self._last_tick) is False:\n   File \"/home/tito/code/kivy/kivy/clock.py\", line 280, in tick\n     ret = callback(self._dt)\n   File \"/home/tito/code/kivy/kivy/animation.py\", line 289, in _update\n     self.dispatch('on_progress', widget, progress)\n   File \"_event.pyx\", line 272, in kivy._event.EventDispatcher.dispatch (kivy/_event.c:3992)\n   File \"/home/tito/code/kivy/kivy/weakmethod.py\", line 42, in __call__\n     if self.proxy:\n ReferenceError: weakly-referenced object no longer exists\n```\n\n", "before_files": [{"content": "'''\nWeak Method\n===========\n\nThe :class:`WeakMethod` is used in the Clock class to allow a reference\nto a bound method that permits the associated object to be garbage collected.\nCheck examples/core/clock_method.py for more information.\n\nThis WeakMethod class is taken from the recipe\nhttp://code.activestate.com/recipes/81253/, based on the nicodemus version.\n(thanks to him !)\n'''\n\nimport weakref\nimport sys\n\nif sys.version > '3':\n\n    class WeakMethod:\n        '''Implementation of a\n        `weakref <http://en.wikipedia.org/wiki/Weak_reference>`_\n        for functions and bound methods.\n        '''\n        def __init__(self, method):\n            self.method = None\n            self.method_name = None\n            try:\n                if method.__self__ is not None:\n                    self.method_name = method.__func__.__name__\n                    self.proxy = weakref.proxy(method.__self__)\n                else:\n                    self.method = method\n                    self.proxy = None\n            except AttributeError:\n                self.method = method\n                self.proxy = None\n\n        def __call__(self):\n            '''Return a new bound-method like the original, or the\n            original function if it was just a function or unbound\n            method.\n            Returns None if the original object doesn't exist.\n            '''\n            if self.proxy:\n                return getattr(self.proxy, self.method_name)\n            return self.method\n\n        def is_dead(self):\n            '''Returns True if the referenced callable was a bound method and\n            the instance no longer exists. Otherwise, return False.\n            '''\n            return self.proxy is not None and not bool(dir(self.proxy))\n\n        def __repr__(self):\n            return '<WeakMethod proxy={} method={} method_name={}>'.format(\n                    self.proxy, self.method, self.method_name)\n\nelse:\n\n    import new\n\n    class WeakMethod(object):\n        '''Implementation of a\n        `weakref <http://en.wikipedia.org/wiki/Weak_reference>`_\n        for functions and bound methods.\n        '''\n\n        def __init__(self, method):\n            try:\n                if method.__self__ is not None:\n                    # bound method\n                    self._obj = weakref.ref(method.im_self)\n                else:\n                    # unbound method\n                    self._obj = None\n                self._func = method.im_func\n                self._class = method.im_class\n            except AttributeError:\n                # not a method\n                self._obj = None\n                self._func = method\n                self._class = None\n\n        def __call__(self):\n            '''Return a new bound-method like the original, or the\n            original function if it was just a function or unbound\n            method.\n            Returns None if the original object doesn't exist.\n            '''\n            if self.is_dead():\n                return None\n            if self._obj is not None:\n                return new.instancemethod(self._func, self._obj(), self._class)\n            else:\n                # we don't have an instance: return just the function\n                return self._func\n\n        def is_dead(self):\n            '''Returns True if the referenced callable was a bound method and\n            the instance no longer exists. Otherwise, return False.\n            '''\n            return self._obj is not None and self._obj() is None\n\n        def __eq__(self, other):\n            try:\n                return type(self) is type(other) and self() == other()\n            except:\n                return False\n\n        def __ne__(self, other):\n            return not self == other\n\n", "path": "kivy/weakmethod.py"}, {"content": "'''\nFactory object\n==============\n\nThe factory can be used to automatically register any class or module\nand instantiate classes from it anywhere in your project. It is an\nimplementation of the\n`Factory Pattern <http://en.wikipedia.org/wiki/Factory_pattern>`_.\n\nThe class list and available modules are automatically generated by setup.py.\n\nExample for registering a class/module::\n\n    >>> from kivy.factory import Factory\n    >>> Factory.register('Widget', module='kivy.uix.widget')\n    >>> Factory.register('Vector', module='kivy.vector')\n\nExample of using the Factory::\n\n    >>> from kivy.factory import Factory\n    >>> widget = Factory.Widget(pos=(456,456))\n    >>> vector = Factory.Vector(9, 2)\n\nExample using a class name::\n\n    >>> from kivy.factory import Factory\n    >>> Factory.register('MyWidget', cls=MyWidget)\n\nBy default, the first classname you register via the factory is permanent.\nIf you wish to change the registered class, you need to unregister the classname\nbefore you re-assign it::\n\n    >>> from kivy.factory import Factory\n    >>> Factory.register('MyWidget', cls=MyWidget)\n    >>> widget = Factory.MyWidget()\n    >>> Factory.unregister('MyWidget')\n    >>> Factory.register('MyWidget', cls=CustomWidget)\n    >>> customWidget = Factory.MyWidget()\n'''\n\n__all__ = ('Factory', 'FactoryException')\n\nfrom kivy.logger import Logger\n\n\nclass FactoryException(Exception):\n    pass\n\n\nclass FactoryBase(object):\n\n    def __init__(self):\n        super(FactoryBase, self).__init__()\n        self.classes = {}\n\n    def is_template(self, classname):\n        '''Return True if the classname is a template from the\n        :class:`~kivy.lang.Builder`.\n\n        .. versionadded:: 1.0.5\n        '''\n        if classname in self.classes:\n            return self.classes[classname]['is_template']\n        else:\n            return False\n\n    def register(self, classname, cls=None, module=None, is_template=False,\n            baseclasses=None, filename=None):\n        '''Register a new classname referring to a real class or\n        class definition in a module.\n\n        .. versionchanged:: 1.7.0\n            :data:`baseclasses` and :data:`filename` added\n\n        .. versionchanged:: 1.0.5\n            :data:`is_template` has been added in 1.0.5.\n        '''\n        if cls is None and module is None and baseclasses is None:\n            raise ValueError(\n                'You must specify either cls= or module= or baseclasses =')\n        if classname in self.classes:\n            return\n        self.classes[classname] = {\n            'module': module,\n            'cls': cls,\n            'is_template': is_template,\n            'baseclasses': baseclasses,\n            'filename': filename}\n\n    def unregister(self, *classnames):\n        '''Unregisters the classnames previously registered via the\n        register method. This allows the same classnames to be re-used in\n        different contexts.\n\n        .. versionadded:: 1.7.1\n        '''\n        for classname in classnames:\n            if classname in self.classes:\n                self.classes.pop(classname)\n\n    def unregister_from_filename(self, filename):\n        '''Unregister all the factory objects related to the filename passed in\n        the parameter.\n\n        .. versionadded:: 1.7.0\n        '''\n        to_remove = [x for x in self.classes\n                if self.classes[x]['filename'] == filename]\n        for name in to_remove:\n            del self.classes[name]\n\n    def __getattr__(self, name):\n        classes = self.classes\n        if name not in classes:\n            raise FactoryException('Unknown class <%s>' % name)\n\n        item = classes[name]\n        cls = item['cls']\n\n        # No class to return, import the module\n        if cls is None:\n            if item['module']:\n                module = __import__(name=item['module'], fromlist='.')\n                if not hasattr(module, name):\n                    raise FactoryException(\n                        'No class named <%s> in module <%s>' % (\n                        name, item['module']))\n                cls = item['cls'] = getattr(module, name)\n\n            elif item['baseclasses']:\n                rootwidgets = []\n                for basecls in item['baseclasses'].split('+'):\n                    rootwidgets.append(Factory.get(basecls))\n                cls = item['cls'] = type(name, tuple(rootwidgets), {})\n\n            else:\n                raise FactoryException('No information to create the class')\n\n        return cls\n\n    get = __getattr__\n\n\n#: Factory instance to use for getting new classes\nFactory = FactoryBase()\n\n# Now import the file with all registers\n# automatically generated by build_factory\nimport kivy.factory_registers\nLogger.info('Factory: %d symbols loaded' % len(Factory.classes))\n\nif __name__ == '__main__':\n    Factory.register('Vector', module='kivy.vector')\n    Factory.register('Widget', module='kivy.uix.widget')\n\n", "path": "kivy/factory.py"}], "after_files": [{"content": "'''\nWeak Method\n===========\n\nThe :class:`WeakMethod` is used in the Clock class to allow a reference\nto a bound method that permits the associated object to be garbage collected.\nCheck examples/core/clock_method.py for more information.\n\nThis WeakMethod class is taken from the recipe\nhttp://code.activestate.com/recipes/81253/, based on the nicodemus version.\n(thanks to him !)\n'''\n\nimport weakref\nimport sys\n\nif sys.version > '3':\n\n    class WeakMethod:\n        '''Implementation of a\n        `weakref <http://en.wikipedia.org/wiki/Weak_reference>`_\n        for functions and bound methods.\n        '''\n        def __init__(self, method):\n            self.method = None\n            self.method_name = None\n            try:\n                if method.__self__ is not None:\n                    self.method_name = method.__func__.__name__\n                    self.proxy = weakref.proxy(method.__self__)\n                else:\n                    self.method = method\n                    self.proxy = None\n            except AttributeError:\n                self.method = method\n                self.proxy = None\n\n        def __call__(self):\n            '''Return a new bound-method like the original, or the\n            original function if it was just a function or unbound\n            method.\n            Returns None if the original object doesn't exist.\n            '''\n            try:\n                if self.proxy:\n                    return getattr(self.proxy, self.method_name)\n            except ReferenceError:\n                pass\n            return self.method\n\n        def is_dead(self):\n            '''Returns True if the referenced callable was a bound method and\n            the instance no longer exists. Otherwise, return False.\n            '''\n            return self.proxy is not None and not bool(dir(self.proxy))\n\n        def __repr__(self):\n            return '<WeakMethod proxy={} method={} method_name={}>'.format(\n                    self.proxy, self.method, self.method_name)\n\nelse:\n\n    import new\n\n    class WeakMethod(object):\n        '''Implementation of a\n        `weakref <http://en.wikipedia.org/wiki/Weak_reference>`_\n        for functions and bound methods.\n        '''\n\n        def __init__(self, method):\n            try:\n                if method.__self__ is not None:\n                    # bound method\n                    self._obj = weakref.ref(method.im_self)\n                else:\n                    # unbound method\n                    self._obj = None\n                self._func = method.im_func\n                self._class = method.im_class\n            except AttributeError:\n                # not a method\n                self._obj = None\n                self._func = method\n                self._class = None\n\n        def __call__(self):\n            '''Return a new bound-method like the original, or the\n            original function if it was just a function or unbound\n            method.\n            Returns None if the original object doesn't exist.\n            '''\n            if self.is_dead():\n                return None\n            if self._obj is not None:\n                return new.instancemethod(self._func, self._obj(), self._class)\n            else:\n                # we don't have an instance: return just the function\n                return self._func\n\n        def is_dead(self):\n            '''Returns True if the referenced callable was a bound method and\n            the instance no longer exists. Otherwise, return False.\n            '''\n            return self._obj is not None and self._obj() is None\n\n        def __eq__(self, other):\n            try:\n                return type(self) is type(other) and self() == other()\n            except:\n                return False\n\n        def __ne__(self, other):\n            return not self == other\n\n", "path": "kivy/weakmethod.py"}, {"content": "'''\nFactory object\n==============\n\nThe factory can be used to automatically register any class or module\nand instantiate classes from it anywhere in your project. It is an\nimplementation of the\n`Factory Pattern <http://en.wikipedia.org/wiki/Factory_pattern>`_.\n\nThe class list and available modules are automatically generated by setup.py.\n\nExample for registering a class/module::\n\n    >>> from kivy.factory import Factory\n    >>> Factory.register('Widget', module='kivy.uix.widget')\n    >>> Factory.register('Vector', module='kivy.vector')\n\nExample of using the Factory::\n\n    >>> from kivy.factory import Factory\n    >>> widget = Factory.Widget(pos=(456,456))\n    >>> vector = Factory.Vector(9, 2)\n\nExample using a class name::\n\n    >>> from kivy.factory import Factory\n    >>> Factory.register('MyWidget', cls=MyWidget)\n\nBy default, the first classname you register via the factory is permanent.\nIf you wish to change the registered class, you need to unregister the classname\nbefore you re-assign it::\n\n    >>> from kivy.factory import Factory\n    >>> Factory.register('MyWidget', cls=MyWidget)\n    >>> widget = Factory.MyWidget()\n    >>> Factory.unregister('MyWidget')\n    >>> Factory.register('MyWidget', cls=CustomWidget)\n    >>> customWidget = Factory.MyWidget()\n'''\n\n__all__ = ('Factory', 'FactoryException')\n\nfrom kivy.logger import Logger\n\n\nclass FactoryException(Exception):\n    pass\n\n\nclass FactoryBase(object):\n\n    def __init__(self):\n        super(FactoryBase, self).__init__()\n        self.classes = {}\n\n    def is_template(self, classname):\n        '''Return True if the classname is a template from the\n        :class:`~kivy.lang.Builder`.\n\n        .. versionadded:: 1.0.5\n        '''\n        if classname in self.classes:\n            return self.classes[classname]['is_template']\n        else:\n            return False\n\n    def register(self, classname, cls=None, module=None, is_template=False,\n            baseclasses=None, filename=None):\n        '''Register a new classname referring to a real class or\n        class definition in a module.\n\n        .. versionchanged:: 1.7.0\n            :data:`baseclasses` and :data:`filename` added\n\n        .. versionchanged:: 1.0.5\n            :data:`is_template` has been added in 1.0.5.\n        '''\n        if cls is None and module is None and baseclasses is None:\n            raise ValueError(\n                'You must specify either cls= or module= or baseclasses =')\n        if classname in self.classes:\n            return\n        self.classes[classname] = {\n            'module': module,\n            'cls': cls,\n            'is_template': is_template,\n            'baseclasses': baseclasses,\n            'filename': filename}\n\n    def unregister(self, *classnames):\n        '''Unregisters the classnames previously registered via the\n        register method. This allows the same classnames to be re-used in\n        different contexts.\n\n        .. versionadded:: 1.7.1\n        '''\n        for classname in classnames:\n            if classname in self.classes:\n                self.classes.pop(classname)\n\n    def unregister_from_filename(self, filename):\n        '''Unregister all the factory objects related to the filename passed in\n        the parameter.\n\n        .. versionadded:: 1.7.0\n        '''\n        to_remove = [x for x in self.classes\n                if self.classes[x]['filename'] == filename]\n        for name in to_remove:\n            del self.classes[name]\n\n    def __getattr__(self, name):\n        classes = self.classes\n        if name not in classes:\n            if name[0] == name[0].lower():\n                # if trying to access attributes like checking for `bind`\n                # then raise AttributeError\n                raise AttributeError\n            raise FactoryException('Unknown class <%s>' % name)\n\n        item = classes[name]\n        cls = item['cls']\n\n        # No class to return, import the module\n        if cls is None:\n            if item['module']:\n                module = __import__(name=item['module'], fromlist='.')\n                if not hasattr(module, name):\n                    raise FactoryException(\n                        'No class named <%s> in module <%s>' % (\n                        name, item['module']))\n                cls = item['cls'] = getattr(module, name)\n\n            elif item['baseclasses']:\n                rootwidgets = []\n                for basecls in item['baseclasses'].split('+'):\n                    rootwidgets.append(Factory.get(basecls))\n                cls = item['cls'] = type(name, tuple(rootwidgets), {})\n\n            else:\n                raise FactoryException('No information to create the class')\n\n        return cls\n\n    get = __getattr__\n\n\n#: Factory instance to use for getting new classes\nFactory = FactoryBase()\n\n# Now import the file with all registers\n# automatically generated by build_factory\nimport kivy.factory_registers\nLogger.info('Factory: %d symbols loaded' % len(Factory.classes))\n\nif __name__ == '__main__':\n    Factory.register('Vector', module='kivy.vector')\n    Factory.register('Widget', module='kivy.uix.widget')\n\n", "path": "kivy/factory.py"}]}