|
1 # Copyright (c) 2005-2009 Nokia Corporation |
|
2 # |
|
3 # Licensed under the Apache License, Version 2.0 (the "License"); |
|
4 # you may not use this file except in compliance with the License. |
|
5 # You may obtain a copy of the License at |
|
6 # |
|
7 # http://www.apache.org/licenses/LICENSE-2.0 |
|
8 # |
|
9 # Unless required by applicable law or agreed to in writing, software |
|
10 # distributed under the License is distributed on an "AS IS" BASIS, |
|
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
12 # See the License for the specific language governing permissions and |
|
13 # limitations under the License. |
|
14 |
|
15 import sys |
|
16 import os |
|
17 import appuifw |
|
18 import series60_console |
|
19 import e32 |
|
20 |
|
21 |
|
22 class SelfClearingNamespace: |
|
23 |
|
24 def __init__(self): |
|
25 self.namespace={'__builtins__': __builtins__, |
|
26 '__name__': '__main__'} |
|
27 |
|
28 def __del__(self): |
|
29 # Here's a subtle case. The default namespace is deleted at interpreter |
|
30 # exit, but these namespaces aren't since all but the most trivial |
|
31 # scripts create reference cycles between the functions defined in the |
|
32 # script and the namespace of the script. To avoid this we explicitly |
|
33 # clear the old namespace to break these reference cycles. |
|
34 self.namespace.clear() |
|
35 |
|
36 script_namespace = SelfClearingNamespace() |
|
37 |
|
38 |
|
39 def query_and_exec(): |
|
40 |
|
41 def is_py(x): |
|
42 ext=os.path.splitext(x)[1].lower() |
|
43 return ext == '.py' or ext == '.pyc' or ext == '.pyo' |
|
44 |
|
45 script_list = [] |
|
46 script_names = [] |
|
47 final_script_list = [] |
|
48 final_script_names = [] |
|
49 for nickname, path in script_dirs: |
|
50 if os.path.exists(path): |
|
51 script_list = map(lambda x: (nickname + x, path + '\\' + x), |
|
52 map(lambda x: unicode(x, 'utf-8'), |
|
53 filter(is_py, os.listdir(path)))) |
|
54 script_names = map(lambda x: unicode(x[0]), script_list) |
|
55 script_names.reverse() |
|
56 script_list.reverse() |
|
57 final_script_list += script_list |
|
58 final_script_names += script_names |
|
59 |
|
60 index = appuifw.selection_list(final_script_names) |
|
61 # We make a fresh, clean namespace every time we run a new script, but |
|
62 # use the old namespace for the interactive console and btconsole sessions. |
|
63 # This allows you to examine the script environment in a console |
|
64 # session after running a script. |
|
65 global script_namespace |
|
66 |
|
67 script_namespace = SelfClearingNamespace() |
|
68 if index >= 0: |
|
69 execfile(final_script_list[index][1].encode('utf-8'), |
|
70 script_namespace.namespace) |
|
71 |
|
72 |
|
73 def exec_interactive(): |
|
74 import interactive_console |
|
75 interactive_console.Py_console(my_console).interactive_loop( |
|
76 script_namespace.namespace) |
|
77 |
|
78 |
|
79 def exec_btconsole(): |
|
80 import btconsole |
|
81 btconsole.main(script_namespace.namespace) |
|
82 |
|
83 |
|
84 def set_defaults(): |
|
85 appuifw.app.body = my_console.text |
|
86 appuifw.app.title = u'Python' |
|
87 sys.stderr = sys.stdout = my_console |
|
88 appuifw.app.screen = 'normal' |
|
89 appuifw.app.orientation = 'automatic' |
|
90 if appuifw.touch_enabled(): |
|
91 appuifw.app.directional_pad = True |
|
92 else: |
|
93 appuifw.app.directional_pad = False |
|
94 init_options_menu() |
|
95 |
|
96 |
|
97 def show_copyright(): |
|
98 print str(copyright) + u"\nSee www.python.org for more information." |
|
99 |
|
100 |
|
101 def menu_action(f): |
|
102 appuifw.app.menu = [] |
|
103 saved_exit_key_handler = appuifw.app.exit_key_handler |
|
104 |
|
105 try: |
|
106 try: |
|
107 f() |
|
108 finally: |
|
109 appuifw.app.exit_key_handler = saved_exit_key_handler |
|
110 set_defaults() |
|
111 except: |
|
112 import traceback |
|
113 traceback.print_exc() |
|
114 |
|
115 |
|
116 def init_options_menu(): |
|
117 appuifw.app.menu = [(u"Run script", |
|
118 lambda: menu_action(query_and_exec)), |
|
119 (u"Interactive console", |
|
120 lambda: menu_action(exec_interactive)), |
|
121 (u"Bluetooth console", |
|
122 lambda: menu_action(exec_btconsole)), |
|
123 (u"About", |
|
124 lambda: menu_action(show_copyright))] |
|
125 |
|
126 # In case of emu, the path to non-base modules needs to be added |
|
127 if e32.in_emulator(): |
|
128 sys.path.append('c:\\resource\\python25\\python25_repo.zip') |
|
129 |
|
130 script_dirs = [(u'c:', 'c:\\data\\python'), (u'e:', 'e:\\python'), |
|
131 (u'e:', 'e:\\data\\python')] |
|
132 for path in ('c:\\data\\python\\lib', 'e:\\python\\lib'): |
|
133 if os.path.exists(path): |
|
134 sys.path.append(path) |
|
135 |
|
136 my_console = series60_console.Console() |
|
137 set_defaults() |
|
138 lock = e32.Ao_lock() |
|
139 appuifw.app.exit_key_handler = lock.signal |
|
140 print 'Python for S60 Version ' + e32.pys60_version |
|
141 print 'Capabilities Present:', e32.get_capabilities() |
|
142 print '\nSelect:' |
|
143 print '"Options -> Run script" to run a script' |
|
144 print '"Options -> About" to view copyright\n' |
|
145 lock.wait() |
|
146 appuifw.app.set_exit() |