Repository: kivy/kivy

Issue:
Functions imported in kv and previously set variables are not available for #:set
``` python
from kivy.app import App
from kivy.lang import Builder

kv = """
#:import random_color kivy.utils.get_random_color

#:set color random_color()

Widget:
"""


class TestApp(App):
    def build(self):
        return Builder.load_string(kv)

if __name__ == '__main__':
    TestApp().run()
```

``` python
Traceback (most recent call last):
  File "E:\dev\prs\kivy\kivy\lang\parser.py", line 411, in execute_directives
    value = eval(value)
  File "<string>", line 1, in <module>
NameError: name 'random_color' is not defined
 Traceback (most recent call last):
   File "E:\dev\prs\kivy\kivy\lang\parser.py", line 411, in execute_directives
     value = eval(value)
   File "<string>", line 1, in <module>
 NameError: name 'random_color' is not defined

 During handling of the above exception, another exception occurred:

 Traceback (most recent call last):
   File "E:\dev\prs\main\test2.py", line 18, in <module>
     TestApp().run()
   File "E:\dev\prs\kivy\kivy\app.py", line 802, in run
     root = self.build()
   File "E:\dev\prs\main\test2.py", line 15, in build
     return Builder.load_string(kv)
   File "E:\dev\prs\kivy\kivy\lang\builder.py", line 347, in load_string
     parser = Parser(content=string, filename=fn)
   File "E:\dev\prs\kivy\kivy\lang\parser.py", line 391, in __init__
     self.parse(content)
   File "E:\dev\prs\kivy\kivy\lang\parser.py", line 490, in parse
     self.execute_directives()
   File "E:\dev\prs\kivy\kivy\lang\parser.py", line 414, in execute_directives
     raise ParserException(self, ln, 'Invalid value')
 kivy.lang.parser.ParserException: Parser: File "<inline>", line 4:
 ...
       2:#:import random_color kivy.utils.get_random_color
       3:
 >>    4:#:set color random_color()
       5:
       6:Widget:
 ...
 Invalid value
```

Functions imported in kv and previously set variables are not available for #:set
``` python
from kivy.app import App
from kivy.lang import Builder

kv = """
#:import random_color kivy.utils.get_random_color

#:set color random_color()

Widget:
"""


class TestApp(App):
    def build(self):
        return Builder.load_string(kv)

if __name__ == '__main__':
    TestApp().run()
```

``` python
Traceback (most recent call last):
  File "E:\dev\prs\kivy\kivy\lang\parser.py", line 411, in execute_directives
    value = eval(value)
  File "<string>", line 1, in <module>
NameError: name 'random_color' is not defined
 Traceback (most recent call last):
   File "E:\dev\prs\kivy\kivy\lang\parser.py", line 411, in execute_directives
     value = eval(value)
   File "<string>", line 1, in <module>
 NameError: name 'random_color' is not defined

 During handling of the above exception, another exception occurred:

 Traceback (most recent call last):
   File "E:\dev\prs\main\test2.py", line 18, in <module>
     TestApp().run()
   File "E:\dev\prs\kivy\kivy\app.py", line 802, in run
     root = self.build()
   File "E:\dev\prs\main\test2.py", line 15, in build
     return Builder.load_string(kv)
   File "E:\dev\prs\kivy\kivy\lang\builder.py", line 347, in load_string
     parser = Parser(content=string, filename=fn)
   File "E:\dev\prs\kivy\kivy\lang\parser.py", line 391, in __init__
     self.parse(content)
   File "E:\dev\prs\kivy\kivy\lang\parser.py", line 490, in parse
     self.execute_directives()
   File "E:\dev\prs\kivy\kivy\lang\parser.py", line 414, in execute_directives
     raise ParserException(self, ln, 'Invalid value')
 kivy.lang.parser.ParserException: Parser: File "<inline>", line 4:
 ...
       2:#:import random_color kivy.utils.get_random_color
       3:
 >>    4:#:set color random_color()
       5:
       6:Widget:
 ...
 Invalid value
```



Discussion:
Why is the traceback duplicated?

Previously set variables are also not available for set:

``` python
from kivy.app import App
from kivy.lang import Builder

kv = """
#:set index 10
#:set start index + 5

Widget:
"""


class TestApp(App):
    def build(self):
        return Builder.load_string(kv)

if __name__ == '__main__':
    TestApp().run()
```

``` python
Traceback (most recent call last):
  File "E:\dev\prs\kivy\kivy\lang\parser.py", line 411, in execute_directives
    value = eval(value)
  File "<string>", line 1, in <module>
NameError: name 'index' is not defined
 Traceback (most recent call last):
   File "E:\dev\prs\kivy\kivy\lang\parser.py", line 411, in execute_directives
     value = eval(value)
   File "<string>", line 1, in <module>
 NameError: name 'index' is not defined

 During handling of the above exception, another exception occurred:

 Traceback (most recent call last):
   File "E:\dev\prs\main\test2.py", line 17, in <module>
     TestApp().run()
   File "E:\dev\prs\kivy\kivy\app.py", line 802, in run
     root = self.build()
   File "E:\dev\prs\main\test2.py", line 14, in build
     return Builder.load_string(kv)
   File "E:\dev\prs\kivy\kivy\lang\builder.py", line 347, in load_string
     parser = Parser(content=string, filename=fn)
   File "E:\dev\prs\kivy\kivy\lang\parser.py", line 391, in __init__
     self.parse(content)
   File "E:\dev\prs\kivy\kivy\lang\parser.py", line 490, in parse
     self.execute_directives()
   File "E:\dev\prs\kivy\kivy\lang\parser.py", line 414, in execute_directives
     raise ParserException(self, ln, 'Invalid value')
 kivy.lang.parser.ParserException: Parser: File "<inline>", line 3:
 ...
       1:
       2:#:set index 10
 >>    3:#:set start index + 5
       4:
       5:Widget:
 ...
 Invalid value
```

Why is the traceback duplicated?

Previously set variables are also not available for set:

``` python
from kivy.app import App
from kivy.lang import Builder

kv = """
#:set index 10
#:set start index + 5

Widget:
"""


class TestApp(App):
    def build(self):
        return Builder.load_string(kv)

if __name__ == '__main__':
    TestApp().run()
```

``` python
Traceback (most recent call last):
  File "E:\dev\prs\kivy\kivy\lang\parser.py", line 411, in execute_directives
    value = eval(value)
  File "<string>", line 1, in <module>
NameError: name 'index' is not defined
 Traceback (most recent call last):
   File "E:\dev\prs\kivy\kivy\lang\parser.py", line 411, in execute_directives
     value = eval(value)
   File "<string>", line 1, in <module>
 NameError: name 'index' is not defined

 During handling of the above exception, another exception occurred:

 Traceback (most recent call last):
   File "E:\dev\prs\main\test2.py", line 17, in <module>
     TestApp().run()
   File "E:\dev\prs\kivy\kivy\app.py", line 802, in run
     root = self.build()
   File "E:\dev\prs\main\test2.py", line 14, in build
     return Builder.load_string(kv)
   File "E:\dev\prs\kivy\kivy\lang\builder.py", line 347, in load_string
     parser = Parser(content=string, filename=fn)
   File "E:\dev\prs\kivy\kivy\lang\parser.py", line 391, in __init__
     self.parse(content)
   File "E:\dev\prs\kivy\kivy\lang\parser.py", line 490, in parse
     self.execute_directives()
   File "E:\dev\prs\kivy\kivy\lang\parser.py", line 414, in execute_directives
     raise ParserException(self, ln, 'Invalid value')
 kivy.lang.parser.ParserException: Parser: File "<inline>", line 3:
 ...
       1:
       2:#:set index 10
 >>    3:#:set start index + 5
       4:
       5:Widget:
 ...
 Invalid value
```


Resolving patch:
diff --git a/kivy/lang/parser.py b/kivy/lang/parser.py
--- a/kivy/lang/parser.py
+++ b/kivy/lang/parser.py
@@ -408,7 +408,7 @@ def execute_directives(self):
                     Logger.exception('')
                     raise ParserException(self, ln, 'Invalid directive syntax')
                 try:
-                    value = eval(value)
+                    value = eval(value, global_idmap)
                 except:
                     Logger.exception('')
                     raise ParserException(self, ln, 'Invalid value')


Test patch: