1 # Prelude to allow running this as a main program
5 macresource
.need('DITL', 468, "PythonIDE.rsrc")
6 widgetrespathsegs
= [sys
.exec_prefix
, "Mac", "Tools", "IDE", "Widgets.rsrc"]
7 widgetresfile
= os
.path
.join(*widgetrespathsegs
)
8 if not os
.path
.exists(widgetresfile
):
9 widgetrespathsegs
= [os
.pardir
, "Tools", "IDE", "Widgets.rsrc"]
10 widgetresfile
= os
.path
.join(*widgetrespathsegs
)
11 refno
= macresource
.need('CURS', 468, widgetresfile
)
12 if os
.environ
.has_key('PYTHONIDEPATH'):
13 # For development set this environment variable
14 ide_path
= os
.environ
['PYTHONIDEPATH']
16 # We're not a fullblown application
17 idepathsegs
= [sys
.exec_prefix
, "Mac", "Tools", "IDE"]
18 ide_path
= os
.path
.join(*idepathsegs
)
19 if not os
.path
.exists(ide_path
):
20 idepathsegs
= [os
.pardir
, "Tools", "IDE"]
22 ide_path
= os
.path
.join(*([p
]+idepathsegs
))
23 if os
.path
.exists(ide_path
):
27 # We are a fully frozen application
28 ide_path
= sys
.argv
[0]
29 if ide_path
not in sys
.path
:
30 sys
.path
.insert(0, ide_path
)
32 if __name__
== '__main__':
37 from Carbon
import Evt
50 USER_INSTALL_DIR
= os
.path
.join(os
.environ
.get('HOME', ''),
56 class PackageManagerMain(Wapplication
.Application
):
59 self
.preffilepath
= os
.path
.join("Python", "Package Install Manager Prefs")
60 Wapplication
.Application
.__init
__(self
, 'Pimp')
62 from Carbon
import AppleEvents
64 AE
.AEInstallEventHandler(AppleEvents
.kCoreEventClass
, AppleEvents
.kAEOpenApplication
,
66 AE
.AEInstallEventHandler(AppleEvents
.kCoreEventClass
, AppleEvents
.kAEReopenApplication
,
68 AE
.AEInstallEventHandler(AppleEvents
.kCoreEventClass
, AppleEvents
.kAEPrintDocuments
,
70 AE
.AEInstallEventHandler(AppleEvents
.kCoreEventClass
, AppleEvents
.kAEQuitApplication
,
74 # With -D option (OSX command line only) keep stderr, for debugging the IDE
77 if len(sys
.argv
) >= 2 and sys
.argv
[1] == '-D':
78 debug_stderr
= sys
.stderr
80 PyConsole
.installoutput()
82 sys
.stderr
= debug_stderr
86 def makeusermenus(self
):
87 m
= Wapplication
.Menu(self
.menubar
, "File")
88 newitem
= FrameWork
.MenuItem(m
, "Open Standard Database", "N", 'openstandard')
89 openitem
= FrameWork
.MenuItem(m
, "Open"+ELIPSES
, "O", 'open')
90 openURLitem
= FrameWork
.MenuItem(m
, "Open URL"+ELIPSES
, "D", 'openURL')
91 FrameWork
.Separator(m
)
92 closeitem
= FrameWork
.MenuItem(m
, "Close", "W", 'close')
93 ## saveitem = FrameWork.MenuItem(m, "Save", "S", 'save')
94 ## saveasitem = FrameWork.MenuItem(m, "Save as"+ELIPSES, None, 'save_as')
95 ## FrameWork.Separator(m)
97 m
= Wapplication
.Menu(self
.menubar
, "Edit")
98 undoitem
= FrameWork
.MenuItem(m
, "Undo", 'Z', "undo")
99 FrameWork
.Separator(m
)
100 cutitem
= FrameWork
.MenuItem(m
, "Cut", 'X', "cut")
101 copyitem
= FrameWork
.MenuItem(m
, "Copy", "C", "copy")
102 pasteitem
= FrameWork
.MenuItem(m
, "Paste", "V", "paste")
103 FrameWork
.MenuItem(m
, "Clear", None, "clear")
104 FrameWork
.Separator(m
)
105 selallitem
= FrameWork
.MenuItem(m
, "Select all", "A", "selectall")
107 m
= Wapplication
.Menu(self
.menubar
, "Package")
108 runitem
= FrameWork
.MenuItem(m
, "Install", "I", 'install')
109 homepageitem
= FrameWork
.MenuItem(m
, "Visit Homepage", None, 'homepage')
111 self
.openwindowsmenu
= Wapplication
.Menu(self
.menubar
, 'Windows')
112 self
.makeopenwindowsmenu()
113 self
._menustocheck
= [closeitem
,
114 undoitem
, cutitem
, copyitem
, pasteitem
,
116 runitem
, homepageitem
]
118 def quitevent(self
, theAppleEvent
, theReply
):
121 def ignoreevent(self
, theAppleEvent
, theReply
):
124 def opendocsevent(self
, theAppleEvent
, theReply
):
127 parameters
, args
= aetools
.unpackevent(theAppleEvent
)
128 docs
= parameters
['----']
129 if type(docs
) <> type([]):
132 fsr
, a
= doc
.FSResolveAlias(None)
133 path
= fsr
.as_pathname()
134 path
= urllib
.pathname2url(path
)
137 def opendoc(self
, url
):
140 def getabouttext(self
):
141 return "About Package Manager"+ELIPSES
143 def do_about(self
, id, item
, window
, event
):
144 EasyDialogs
.Message("Package Install Manager for Python")
146 def domenu_openstandard(self
, *args
):
149 def domenu_open(self
, *args
):
150 filename
= EasyDialogs
.AskFileForOpen(typeList
=("TEXT",))
152 filename
= urllib
.pathname2url(filename
)
153 self
.opendoc(filename
)
155 def domenu_openURL(self
, *args
):
156 ok
= EasyDialogs
.AskYesNoCancel(
157 "Warning: by opening a non-standard database "
158 "you are trusting the maintainer of it "
159 "to run arbitrary code on your machine.",
162 url
= EasyDialogs
.AskString("URL of database to open:", ok
="Open")
166 def domenu_openbyname(self
, *args
):
167 url
= EasyDialogs
.AskString("Open URL:", ok
="Open")
171 def makeopenwindowsmenu(self
):
172 for i
in range(len(self
.openwindowsmenu
.items
)):
173 self
.openwindowsmenu
.menu
.DeleteMenuItem(1)
174 self
.openwindowsmenu
.items
= []
176 self
._openwindows
= {}
177 for window
in self
._windows
.keys():
178 title
= window
.GetWTitle()
181 windows
.append((title
, window
))
183 for title
, window
in windows
:
185 item
= FrameWork
.MenuItem(self
.openwindowsmenu
, title
, shortcut
, callback
= self
.domenu_openwindows
)
186 self
._openwindows
[item
.item
] = window
187 self
._openwindowscheckmark
= 0
188 self
.checkopenwindowsmenu()
190 def domenu_openwindows(self
, id, item
, window
, event
):
191 w
= self
._openwindows
[item
]
195 def domenu_quit(self
):
198 def domenu_save(self
, *args
):
202 ## import PyConsole, PyEdit
203 for window
in self
._windows
.values():
205 rv
= window
.close() # ignore any errors while quitting
207 rv
= 0 # (otherwise, we can get stuck!)
211 ## PyConsole.console.writeprefs()
212 ## PyConsole.output.writeprefs()
213 ## PyEdit.searchengine.writeprefs()
215 ## # Write to __stderr__ so the msg end up in Console.app and has
216 ## # at least _some_ chance of getting read...
217 ## # But: this is a workaround for way more serious problems with
218 ## # the Python 2.2 Jaguar addon.
219 ## sys.__stderr__.write("*** PythonIDE: Can't write preferences ***\n")
224 def setuppimp(self
, url
):
225 self
.pimpprefs
= pimp
.PimpPreferences()
226 self
.pimpdb
= pimp
.PimpDatabase(self
.pimpprefs
)
227 self
.pimpinstaller
= pimp
.PimpInstaller(self
.pimpdb
)
229 url
= self
.pimpprefs
.pimpDatabase
231 self
.pimpdb
.appendURL(url
)
233 rv
= "Cannot open %s: %s\n" % (url
, arg
)
234 rv
+= "\nSee MacPython Package Manager help page."
236 # Check whether we can write the installation directory.
237 # If not, set to the per-user directory, possibly
238 # creating it, if needed.
239 installDir
= self
.pimpprefs
.installDir
240 if not os
.access(installDir
, os
.R_OK|os
.W_OK|os
.X_OK
):
241 rv
= self
.setuserinstall(1)
243 return self
.pimpprefs
.check()
247 self
.pimpprefs
= None
249 self
.pimpinstaller
= None
252 def setuserinstall(self
, onoff
):
255 if not os
.path
.exists(USER_INSTALL_DIR
):
257 os
.makedirs(USER_INSTALL_DIR
)
260 if not USER_INSTALL_DIR
in sys
.path
:
263 self
.pimpprefs
.setInstallDir(USER_INSTALL_DIR
)
265 self
.pimpprefs
.setInstallDir(None)
266 rv
= rv
+ self
.pimpprefs
.check()
269 def getuserinstall(self
):
270 return self
.pimpprefs
.installDir
== USER_INSTALL_DIR
272 def getbrowserdata(self
, show_hidden
=1):
273 packages
= self
.pimpdb
.list()
275 self
.packages
= packages
279 name
= pkg
.fullname()
280 if name
[0] == '(' and name
[-1] == ')' and not show_hidden
:
282 self
.packages
.append(pkg
)
284 for pkg
in self
.packages
:
285 name
= pkg
.fullname()
286 status
, _
= pkg
.installed()
287 description
= pkg
.description()
288 rv
.append((status
, name
, description
))
291 def getstatus(self
, number
):
292 pkg
= self
.packages
[number
]
293 return pkg
.installed()
295 def installpackage(self
, sel
, output
, recursive
, force
):
296 pkg
= self
.packages
[sel
]
297 list, messages
= self
.pimpinstaller
.prepareInstall(pkg
, force
, recursive
)
300 messages
= self
.pimpinstaller
.install(list, output
)
303 class PackageBrowser(PimpInterface
):
305 def __init__(self
, url
= None):
307 messages
= self
.setuppimp(url
)
310 self
.showmessages(messages
)
315 def setupwidgets(self
):
317 STATUS_POS
= INSTALL_POS
- 70
318 self
.w
= W
.Window((580, 400), "Python Install Manager", minsize
= (400, 200), tabbable
= 0)
319 self
.w
.titlebar
= W
.TextBox((4, 8, 60, 18), 'Packages:')
320 self
.w
.hidden_button
= W
.CheckBox((-100, 4, 0, 18), 'Show Hidden', self
.updatestatus
)
321 data
= self
.getbrowserdata()
322 self
.w
.packagebrowser
= W
.MultiList((4, 24, 0, STATUS_POS
-2), data
, self
.listhit
, cols
=3)
324 self
.w
.installed_l
= W
.TextBox((4, STATUS_POS
, 60, 12), 'Installed:')
325 self
.w
.installed
= W
.TextBox((64, STATUS_POS
, 0, 12), '')
326 self
.w
.message_l
= W
.TextBox((4, STATUS_POS
+20, 60, 12), 'Status:')
327 self
.w
.message
= W
.TextBox((64, STATUS_POS
+20, 0, 12), '')
328 self
.w
.homepage_button
= W
.Button((4, STATUS_POS
+40, 96, 18), 'View homepage', self
.do_homepage
)
330 self
.w
.divline
= W
.HorizontalLine((0, INSTALL_POS
-4, 0, 0))
331 self
.w
.verbose_button
= W
.CheckBox((84, INSTALL_POS
+4, 60, 18), 'Verbose')
332 self
.w
.recursive_button
= W
.CheckBox((146, INSTALL_POS
+4, 120, 18), 'Install dependencies', self
.updatestatus
)
333 self
.w
.recursive_button
.set(1)
334 self
.w
.force_button
= W
.CheckBox((268, INSTALL_POS
+4, 70, 18), 'Overwrite', self
.updatestatus
)
335 self
.w
.user_button
= W
.CheckBox((340, INSTALL_POS
+4, 140, 18), 'For Current User Only', self
.do_user
)
336 self
.w
.install_button
= W
.Button((4, INSTALL_POS
+4, 56, 18), 'Install:', self
.do_install
)
339 def updatestatus(self
):
340 sel
= self
.w
.packagebrowser
.getselection()
341 data
= self
.getbrowserdata(self
.w
.hidden_button
.get())
342 self
.w
.packagebrowser
.setitems(data
)
343 self
.w
.user_button
.set(self
.getuserinstall())
345 self
.w
.installed
.set('')
346 self
.w
.message
.set('')
347 self
.w
.install_button
.enable(0)
348 self
.w
.homepage_button
.enable(0)
349 self
.w
.verbose_button
.enable(0)
350 self
.w
.recursive_button
.enable(0)
351 self
.w
.force_button
.enable(0)
352 self
.w
.user_button
.enable(0)
355 self
.w
.packagebrowser
.setselection([sel
])
356 installed
, message
= self
.getstatus(sel
)
357 self
.w
.installed
.set(installed
)
358 self
.w
.message
.set(message
)
359 self
.w
.install_button
.enable(installed
!= "yes" or self
.w
.force_button
.get())
360 self
.w
.homepage_button
.enable(not not self
.packages
[sel
].homepage())
361 self
.w
.verbose_button
.enable(1)
362 self
.w
.recursive_button
.enable(1)
363 self
.w
.force_button
.enable(1)
364 self
.w
.user_button
.enable(1)
366 def listhit(self
, *args
, **kwargs
):
369 def do_install(self
):
370 sel
= self
.w
.packagebrowser
.getselection()[0]
371 if self
.w
.verbose_button
.get():
375 recursive
= self
.w
.recursive_button
.get()
376 force
= self
.w
.force_button
.get()
377 messages
= self
.installpackage(sel
, output
, recursive
, force
)
384 self
.showmessages(messages
)
386 def showmessages(self
, messages
):
388 if type(messages
) == list:
389 messages
= '\n'.join(messages
)
390 if self
.w
.verbose_button
.get():
391 sys
.stdout
.write(messages
+ '\n')
392 EasyDialogs
.Message(messages
)
394 def do_homepage(self
):
395 sel
= self
.w
.packagebrowser
.getselection()[0]
400 self
.ic
.launchurl(self
.packages
[sel
].homepage())
403 messages
= self
.setuserinstall(self
.w
.user_button
.get())
405 self
.showmessages(messages
)
407 if __name__
== '__main__':