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()
114 self
._menustocheck
= [closeitem
,
115 undoitem
, cutitem
, copyitem
, pasteitem
,
117 runitem
, homepageitem
]
119 def makehelpmenu(self
):
120 python_app
= os
.path
.join(sys
.prefix
, 'Resources/Python.app')
121 help_source
= os
.path
.join(python_app
, 'Contents/Resources/English.lproj/Documentation')
122 hashelp
= os
.path
.isdir(help_source
)
124 self
.helpmenu
= m
= self
.gethelpmenu()
125 helpitem1
= FrameWork
.MenuItem(m
, "PackageManager Help", None, self
.domenu_packmanhelp
)
126 helpitem1
.enable(hashelp
)
127 helpitem2
= FrameWork
.MenuItem(m
, "MacPython Help", None, self
.domenu_pythonhelp
)
128 helpitem2
.enable(hashelp
)
130 def quitevent(self
, theAppleEvent
, theReply
):
133 def ignoreevent(self
, theAppleEvent
, theReply
):
136 def opendocsevent(self
, theAppleEvent
, theReply
):
139 parameters
, args
= aetools
.unpackevent(theAppleEvent
)
140 docs
= parameters
['----']
141 if type(docs
) <> type([]):
144 fsr
, a
= doc
.FSResolveAlias(None)
145 path
= fsr
.as_pathname()
146 path
= urllib
.pathname2url(path
)
149 def opendoc(self
, url
):
152 def getabouttext(self
):
153 return "About Package Manager"+ELIPSES
155 def do_about(self
, id, item
, window
, event
):
156 EasyDialogs
.Message("Package Install Manager for Python")
158 def domenu_openstandard(self
, *args
):
161 def domenu_open(self
, *args
):
162 filename
= EasyDialogs
.AskFileForOpen(typeList
=("TEXT",))
164 filename
= urllib
.pathname2url(filename
)
165 self
.opendoc(filename
)
167 def domenu_openURL(self
, *args
):
168 ok
= EasyDialogs
.AskYesNoCancel(
169 "Warning: by opening a non-standard database "
170 "you are trusting the maintainer of it "
171 "to run arbitrary code on your machine.",
174 url
= EasyDialogs
.AskString("URL of database to open:", ok
="Open")
178 def domenu_openbyname(self
, *args
):
179 url
= EasyDialogs
.AskString("Open URL:", ok
="Open")
183 def makeopenwindowsmenu(self
):
184 for i
in range(len(self
.openwindowsmenu
.items
)):
185 self
.openwindowsmenu
.menu
.DeleteMenuItem(1)
186 self
.openwindowsmenu
.items
= []
188 self
._openwindows
= {}
189 for window
in self
._windows
.keys():
190 title
= window
.GetWTitle()
193 windows
.append((title
, window
))
195 for title
, window
in windows
:
197 item
= FrameWork
.MenuItem(self
.openwindowsmenu
, title
, shortcut
, callback
= self
.domenu_openwindows
)
198 self
._openwindows
[item
.item
] = window
199 self
._openwindowscheckmark
= 0
200 self
.checkopenwindowsmenu()
202 def domenu_openwindows(self
, id, item
, window
, event
):
203 w
= self
._openwindows
[item
]
207 def domenu_quit(self
):
210 def domenu_save(self
, *args
):
213 def domenu_pythonhelp(self
, *args
):
214 from Carbon
import AH
215 AH
.AHGotoPage("MacPython Help", None, None)
217 def domenu_packmanhelp(self
, *args
):
218 from Carbon
import AH
219 AH
.AHGotoPage("MacPython Help", "packman.html", None)
222 ## import PyConsole, PyEdit
223 for window
in self
._windows
.values():
225 rv
= window
.close() # ignore any errors while quitting
227 rv
= 0 # (otherwise, we can get stuck!)
231 ## PyConsole.console.writeprefs()
232 ## PyConsole.output.writeprefs()
233 ## PyEdit.searchengine.writeprefs()
235 ## # Write to __stderr__ so the msg end up in Console.app and has
236 ## # at least _some_ chance of getting read...
237 ## # But: this is a workaround for way more serious problems with
238 ## # the Python 2.2 Jaguar addon.
239 ## sys.__stderr__.write("*** PythonIDE: Can't write preferences ***\n")
244 def setuppimp(self
, url
):
245 self
.pimpprefs
= pimp
.PimpPreferences()
246 self
.pimpdb
= pimp
.PimpDatabase(self
.pimpprefs
)
247 self
.pimpinstaller
= pimp
.PimpInstaller(self
.pimpdb
)
249 url
= self
.pimpprefs
.pimpDatabase
251 self
.pimpdb
.appendURL(url
)
253 rv
= "Cannot open %s: %s\n" % (url
, arg
)
254 rv
+= "\nSee MacPython Package Manager help page."
256 # Check whether we can write the installation directory.
257 # If not, set to the per-user directory, possibly
258 # creating it, if needed.
259 installDir
= self
.pimpprefs
.installDir
260 if not os
.access(installDir
, os
.R_OK|os
.W_OK|os
.X_OK
):
261 rv
= self
.setuserinstall(1)
263 return self
.pimpprefs
.check()
267 self
.pimpprefs
= None
269 self
.pimpinstaller
= None
272 def setuserinstall(self
, onoff
):
275 if not os
.path
.exists(USER_INSTALL_DIR
):
277 os
.makedirs(USER_INSTALL_DIR
)
280 if not USER_INSTALL_DIR
in sys
.path
:
283 self
.pimpprefs
.setInstallDir(USER_INSTALL_DIR
)
285 self
.pimpprefs
.setInstallDir(None)
286 rv
= rv
+ self
.pimpprefs
.check()
289 def getuserinstall(self
):
290 return self
.pimpprefs
.installDir
== USER_INSTALL_DIR
292 def getbrowserdata(self
, show_hidden
=1):
293 packages
= self
.pimpdb
.list()
295 self
.packages
= packages
299 name
= pkg
.fullname()
300 if name
[0] == '(' and name
[-1] == ')' and not show_hidden
:
302 self
.packages
.append(pkg
)
304 for pkg
in self
.packages
:
305 name
= pkg
.fullname()
306 status
, _
= pkg
.installed()
307 description
= pkg
.description()
308 description_line1
= description
.split('\n')[0]
309 rv
.append((status
, name
, description_line1
))
312 def getstatus(self
, number
):
313 pkg
= self
.packages
[number
]
314 return pkg
.installed()
316 def installpackage(self
, sel
, output
, recursive
, force
):
317 pkg
= self
.packages
[sel
]
318 list, messages
= self
.pimpinstaller
.prepareInstall(pkg
, force
, recursive
)
321 messages
= self
.pimpinstaller
.install(list, output
)
324 class PackageBrowser(PimpInterface
):
326 def __init__(self
, url
= None):
328 messages
= self
.setuppimp(url
)
331 self
.showmessages(messages
)
336 def setupwidgets(self
):
337 DESCRIPTION_HEIGHT
= 140
339 STATUS_POS
= INSTALL_POS
- (70 + DESCRIPTION_HEIGHT
)
340 self
.w
= W
.Window((580, 600), "Python Install Manager", minsize
= (400, 400), tabbable
= 0)
341 self
.w
.titlebar
= W
.TextBox((4, 8, 60, 18), 'Packages:')
342 self
.w
.hidden_button
= W
.CheckBox((-100, 4, 0, 18), 'Show Hidden', self
.updatestatus
)
343 data
= self
.getbrowserdata()
344 self
.w
.packagebrowser
= W
.MultiList((4, 24, 0, STATUS_POS
-2), data
, self
.listhit
, cols
=3)
346 self
.w
.installed_l
= W
.TextBox((4, STATUS_POS
, 70, 12), 'Installed:')
347 self
.w
.installed
= W
.TextBox((74, STATUS_POS
, 0, 12), '')
348 self
.w
.message_l
= W
.TextBox((4, STATUS_POS
+20, 70, 12), 'Status:')
349 self
.w
.message
= W
.TextBox((74, STATUS_POS
+20, 0, 12), '')
350 self
.w
.homepage_button
= W
.Button((4, STATUS_POS
+40, 96, 18), 'View homepage', self
.do_homepage
)
351 self
.w
.description_l
= W
.TextBox((4, STATUS_POS
+70, 70, 12), 'Description:')
352 self
.w
.description
= W
.EditText((74, STATUS_POS
+70, 0, DESCRIPTION_HEIGHT
-4))
354 self
.w
.divline
= W
.HorizontalLine((0, INSTALL_POS
-4, 0, 0))
355 self
.w
.verbose_button
= W
.CheckBox((84, INSTALL_POS
+4, 60, 18), 'Verbose')
356 self
.w
.recursive_button
= W
.CheckBox((146, INSTALL_POS
+4, 120, 18), 'Install dependencies', self
.updatestatus
)
357 self
.w
.recursive_button
.set(1)
358 self
.w
.force_button
= W
.CheckBox((268, INSTALL_POS
+4, 70, 18), 'Overwrite', self
.updatestatus
)
359 self
.w
.user_button
= W
.CheckBox((340, INSTALL_POS
+4, 140, 18), 'For Current User Only', self
.do_user
)
360 self
.w
.install_button
= W
.Button((4, INSTALL_POS
+4, 56, 18), 'Install:', self
.do_install
)
362 self
.w
.description
.enable(0)
364 def updatestatus(self
):
365 sel
= self
.w
.packagebrowser
.getselection()
366 data
= self
.getbrowserdata(self
.w
.hidden_button
.get())
367 self
.w
.packagebrowser
.setitems(data
)
368 self
.w
.user_button
.set(self
.getuserinstall())
370 self
.w
.installed
.set('')
371 self
.w
.message
.set('')
372 self
.w
.install_button
.enable(0)
373 self
.w
.homepage_button
.enable(0)
374 self
.w
.description
.set('')
375 self
.w
.verbose_button
.enable(0)
376 self
.w
.recursive_button
.enable(0)
377 self
.w
.force_button
.enable(0)
378 self
.w
.user_button
.enable(0)
381 self
.w
.packagebrowser
.setselection([sel
])
382 installed
, message
= self
.getstatus(sel
)
383 self
.w
.installed
.set(installed
)
384 self
.w
.message
.set(message
)
385 self
.w
.install_button
.enable(installed
!= "yes" or self
.w
.force_button
.get())
386 self
.w
.homepage_button
.enable(not not self
.packages
[sel
].homepage())
387 description
= self
.packages
[sel
].description()
388 description
= description
.splitlines()
389 description
= '\r'.join(description
)
390 self
.w
.description
.set(description
)
391 self
.w
.verbose_button
.enable(1)
392 self
.w
.recursive_button
.enable(1)
393 self
.w
.force_button
.enable(1)
394 self
.w
.user_button
.enable(1)
396 def listhit(self
, *args
, **kwargs
):
399 def do_install(self
):
400 sel
= self
.w
.packagebrowser
.getselection()[0]
401 if self
.w
.verbose_button
.get():
405 recursive
= self
.w
.recursive_button
.get()
406 force
= self
.w
.force_button
.get()
407 messages
= self
.installpackage(sel
, output
, recursive
, force
)
414 self
.showmessages(messages
)
416 def showmessages(self
, messages
):
418 if type(messages
) == list:
419 messages
= '\n'.join(messages
)
420 if self
.w
.verbose_button
.get():
421 sys
.stdout
.write(messages
+ '\n')
422 EasyDialogs
.Message(messages
)
424 def do_homepage(self
):
425 sel
= self
.w
.packagebrowser
.getselection()[0]
430 self
.ic
.launchurl(self
.packages
[sel
].homepage())
433 messages
= self
.setuserinstall(self
.w
.user_button
.get())
435 self
.showmessages(messages
)
437 if __name__
== '__main__':