From barry at barrys-emacs.org Mon Sep 18 03:51:49 2023 From: barry at barrys-emacs.org (Barry) Date: Mon, 18 Sep 2023 08:51:49 +0100 Subject: [Pythonmac-SIG] Python Launcher Pops Up When Py-based App Is Running (Mac) In-Reply-To: References: Message-ID: > On 18 Sep 2023, at 04:38, James Greenham via Python-list wrote: > > On the face of it, the Python-Mac mailing list is largely inactive so I'm posting here since it looks like this one is livelier. It still gets replies to questions, but slowly. You might find asking on https://discuss.python.org/ works better. Barry -------------- next part -------------- An HTML attachment was scrubbed... URL: From ronaldoussoren at mac.com Sun Sep 24 05:45:01 2023 From: ronaldoussoren at mac.com (Ronald Oussoren) Date: Sun, 24 Sep 2023 11:45:01 +0200 Subject: [Pythonmac-SIG] [ANN] PyObjC 10.0 released Message-ID: <7B20AF5F-1AC0-4EBF-9A08-292E9D6F6EE6@mac.com> Hi, I?ve tagged PyObjC 10.0 and am in the process of uploading to PyPI. The major change in this version is support for macOS Sonoma, just in time for the release of that version of macOS. Some other changes: * The lazy loading machinery no longer uses ?objc.ObjCLazyModule? * Python 3.7 is no longer supported * objc.simd was restructured, hopefully without impact on user code See the full changelog of https://pyobjc.readthedocs.io/en/latest/changelog.html for a detailed list of changes. Ronald ? Twitter / micro.blog: @ronaldoussoren Mastodon: @ronald at blog.ronaldoussoren.net. Blog: https://blog.ronaldoussoren.net/ -------------- next part -------------- An HTML attachment was scrubbed... URL: From cooler9.t at icloud.com Sat Sep 16 21:21:04 2023 From: cooler9.t at icloud.com (James Greenham) Date: Sun, 17 Sep 2023 01:21:04 -0000 Subject: [Pythonmac-SIG] Python Launcher Pops Up When Py-based App Is Running Message-ID: Hello, I run macOS Mojave with Python 2.7. I have an old Dashboard widget (last modified in 2009) that appears to use Python as well. The widget captures the full Safari web-page. It works seamlessly on earlier macOS systems but hangs in 10.14. The widget's core functions constitute code of the script that I'm pasting in this message. The problem is that as soon as the execution reaches the image processing stage it gets stuck which manifests by Python Launcher popping up in Dock and is trying forever until I quit the launcher that force-quits the widget showing the error icon. The issue seems to originate in the doGrab handler (module or whatever the correct Python term fits the definition) immediately following the print "Processing Image..." line: it's the message the widget displays at getting stalled. I( checked that Python 2.7 is installed in the default location at /usr/bin. However, I have the binaries idle3, idle3.10, pip3, pip3.10 in /usr/local/bin. Is that remedied? The script's environment set to python, i.e. to python 2.7 so that shouldn't be the encumbrance. Am I correct? #!/usr/bin/env python # -*- coding: utf-8 -*- # OR: # coding=utf-8 __version__ = "0.6" # # Based on Paul Hammond's webkit2png script - make screenshots of webpages # http://www.paulhammond.org/webkit2png # # Modified by Paulo Avila for the Page Capture widget # # The original source code (v0.5) belongs to Paul Hammond (see notice below). # Any and all code added after is Copyright (c) 2009 Paulo Avila. # # Modification Log by Paul Avila # # 2009.04.21 - Changed almost all the output messages in order to behave properly with my Page Capture widget # 2009.04.21 - Added function headers # 2009.04.21 - Properly flush the output buffers so that messages display immediately # 2009.04.21 - Changed encoding of this file to UTF-8 # 2009.04.25 - Updated how files are named: " > .png" # 2009.04.25 - Files are now named with the full URL excluding protocol (http://) and arguments (...?*) # # Copyright (c) 2009 Paul Hammond # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # import sys import optparse try: import Foundation import WebKit import AppKit import objc except ImportError: #print "Cannot find pyobjc library files. Are you sure it is installed?" print "Mac OS X 10.5 or higher is required." sys.stdout.flush() sys.exit() class AppDelegate (Foundation.NSObject): # what happens when the app starts up def applicationDidFinishLaunching_(self, aNotification): webview = aNotification.object().windows()[0].contentView() webview.frameLoadDelegate().getURL(webview) class WebkitLoad (Foundation.NSObject, WebKit.protocols.WebFrameLoadDelegate): # what happens if something goes wrong while loading def webView_didFailLoadWithError_forFrame_(self,webview,error,frame): #print " ... something went wrong" print "Unable to load WebKit." sys.stdout.flush() self.getURL(webview) def webView_didFailProvisionalLoadWithError_forFrame_(self,webview,error,frame): #print " ... something went wrong" print "Check URL or Internet connection." sys.stdout.flush() self.getURL(webview) #--------------------------------------------------- #7 - Generates the filename. def makeFilename(self,URL,options): # make the filename if options.filename: filename = options.filename elif options.md5: try: import md5 except ImportError: print "--md5 requires python md5 library" sys.stdout.flush() AppKit.NSApplication.sharedApplication().terminate_(None) filename = md5.new(URL).hexdigest() else: import re # filename = re.sub('\W','',URL); #\W is the same as [^a-zA-Z0-9_] #-------- #remove anything after (and including) a question mark URL = re.sub("\?.*$", "", URL); #arg = URL.find("?"); #if arg >= 0: # URL = URL[0:arg]; #remove the protocol string in the beginning (SSL or not) URL = re.sub("^https?://", "", URL); #-- Page Capture # (start) import os dir = os.path.abspath(os.path.expanduser(options.dir)); count = 1; while os.access(dir + "/Page Capture " + str(count) + ".png", os.F_OK): count += 1; filename = "Page Capture " + str(count); #-- Page Capture # (end) #-- Full URL (start) #replace forward slashes with colons to allow to forward slashes in the filename (OS X's HFS+ allows for this) # filename = re.sub("/", ":", URL); #max filename length permitted is 255. (255 - 4 = 251). (4 is the length of the extenion '.png') # if len(filename) > 251: # filename = filename[0:248] + "..."; #-- Full URL (end) #-- Domain > File (start) # URL = URL.split("/"); #isolate just the domain # domain = URL[0]; #domain = re.sub("/.*$", "", URL); #domain = URL[0:URL.find("/")]; #isolate just the file, if it doesn't exist, make it blank # file = URL[len(URL)-1]; # if len(URL) == 1: # file = ""; # filename = domain + " > " + file; #print "d= '" + domain + "'"; #print "f= '" + file + "'"; #-- Domain > File (end) #-------- if options.datestamp: import time now = time.strftime("%Y%m%d") # now = time.strftime("%Y%m%d%H%M%S") filename = now + "-" + filename # import os # dir = os.path.abspath(os.path.expanduser(options.dir)) # return os.path.join(dir,filename) return filename #--------------------------------------------------- #8 - Saves the captured image(s) to the right place. def saveImages(self,bitmapdata,filename,options): # save the fullsize png if options.fullsize: bitmapdata.representationUsingType_properties_(AppKit.NSPNGFileType,None).writeToFile_atomically_(filename + "-full.png",objc.YES) if options.thumb or options.clipped: # work out how big the thumbnail is width = bitmapdata.pixelsWide() height = bitmapdata.pixelsHigh() thumbWidth = (width * options.scale) thumbHeight = (height * options.scale) # make the thumbnails in a scratch image scratch = AppKit.NSImage.alloc().initWithSize_( Foundation.NSMakeSize(thumbWidth,thumbHeight)) scratch.lockFocus() AppKit.NSGraphicsContext.currentContext().setImageInterpolation_( AppKit.NSImageInterpolationHigh) thumbRect = Foundation.NSMakeRect(0.0, 0.0, thumbWidth, thumbHeight) clipRect = Foundation.NSMakeRect(0.0, thumbHeight-options.clipheight, options.clipwidth, options.clipheight) bitmapdata.drawInRect_(thumbRect) thumbOutput = AppKit.NSBitmapImageRep.alloc().initWithFocusedViewRect_(thumbRect) clipOutput = AppKit.NSBitmapImageRep.alloc().initWithFocusedViewRect_(clipRect) scratch.unlockFocus() # save the thumbnails as pngs if options.thumb: thumbOutput.representationUsingType_properties_( AppKit.NSPNGFileType,None ).writeToFile_atomically_(filename + ".png",objc.YES) # thumbOutput.representationUsingType_properties_( # AppKit.NSPNGFileType,None # ).writeToFile_atomically_(filename + "-thumb.png",objc.YES) if options.clipped: clipOutput.representationUsingType_properties_( AppKit.NSPNGFileType,None ).writeToFile_atomically_(filename + "-clipped.png",objc.YES) #--------------------------------------------------- #1 - Downloads URL contents. def getURL(self,webview): if self.urls: if self.urls[0] == '-': url = sys.stdin.readline().rstrip() if not url: AppKit.NSApplication.sharedApplication().terminate_(None) else: url = self.urls.pop(0) else: AppKit.NSApplication.sharedApplication().terminate_(None) #print "Fetching", url, "..." print "Fetching URL..." sys.stdout.flush() self.resetWebview(webview) webview.mainFrame().loadRequest_(Foundation.NSURLRequest.requestWithURL_(Foundation.NSURL.URLWithString_(url))) if not webview.mainFrame().provisionalDataSource(): #print " ... not a proper url?" print "Invalid URL." sys.stdout.flush() self.getURL(webview) #--------------------------------------------------- #2 - Resets any previous history? def resetWebview(self,webview): rect = Foundation.NSMakeRect(0,0,self.options.initWidth,self.options.initHeight) webview.window().setContentSize_((self.options.initWidth,self.options.initHeight)) webview.setFrame_(rect) #--------------------------------------------------- #5 - Resizes the window. def resizeWebview(self,view): view.window().display() view.window().setContentSize_(view.bounds().size) view.setFrame_(view.bounds()) #--------------------------------------------------- #6 - Turns current webview content into a bitmap. def captureView(self,view): view.lockFocus() bitmapdata = AppKit.NSBitmapImageRep.alloc() bitmapdata.initWithFocusedViewRect_(view.bounds()) view.unlockFocus() return bitmapdata #--------------------------------------------------- #3 - Called for each "piece" of the page. # what happens when the page has finished loading def webView_didFinishLoadForFrame_(self,webview,frame): # don't care about subframes if (frame == webview.mainFrame()): Foundation.NSTimer.scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_( self.options.delay, self, self.doGrab, webview, False) #--------------------------------------------------- #4 - Process the downloaded content (calls 5-8) def doGrab(self,timer): print "Processing image..." sys.stdout.flush() webview = timer.userInfo() view = webview.mainFrame().frameView().documentView() self.resizeWebview(view) URL = webview.mainFrame().dataSource().initialRequest().URL().absoluteString() filename = self.makeFilename(URL, self.options) import os full_path = os.path.join(os.path.abspath(os.path.expanduser(self.options.dir)), filename); bitmapdata = self.captureView(view) self.saveImages(bitmapdata, full_path, self.options) #print " ... done" # ? print "" + filename + " saved to your Desktop." sys.stdout.flush() self.getURL(webview) def main(): # parse the command line usage = """%prog [options] [http://example.net/ ...] examples: %prog http://google.com/ # screengrab google %prog -W 1000 -H 1000 http://google.com/ # bigger screengrab of google %prog -T http://google.com/ # just the thumbnail screengrab %prog -TF http://google.com/ # just thumbnail and fullsize grab %prog -o foo http://google.com/ # save images as "foo-thumb.png" etc %prog - # screengrab urls from stdin %prog -h | less # full documentation""" cmdparser = optparse.OptionParser(usage,version=("webkit2png "+__version__)) # TODO: add quiet/verbose options cmdparser.add_option("-W", "--width",type="float",default=800.0, help="initial (and minimum) width of browser (default: 800)") cmdparser.add_option("-H", "--height",type="float",default=600.0, help="initial (and minimum) height of browser (default: 600)") cmdparser.add_option("--clipwidth",type="float",default=200.0, help="width of clipped thumbnail (default: 200)", metavar="WIDTH") cmdparser.add_option("--clipheight",type="float",default=150.0, help="height of clipped thumbnail (default: 150)", metavar="HEIGHT") cmdparser.add_option("-s", "--scale",type="float",default=0.25, help="scale factor for thumbnails (default: 0.25)") cmdparser.add_option("-m", "--md5", action="store_true", help="use md5 hash for filename (like del.icio.us)") cmdparser.add_option("-o", "--filename", type="string",default="", metavar="NAME", help="save images as NAME-full.png,NAME-thumb.png etc") cmdparser.add_option("-F", "--fullsize", action="store_true", help="only create fullsize screenshot") cmdparser.add_option("-T", "--thumb", action="store_true", help="only create thumbnail sreenshot") cmdparser.add_option("-C", "--clipped", action="store_true", help="only create clipped thumbnail screenshot") cmdparser.add_option("-d", "--datestamp", action="store_true", help="include date in filename") cmdparser.add_option("-D", "--dir",type="string",default="./", help="directory to place images into") cmdparser.add_option("--delay",type="float",default=0, help="delay between page load finishing and screenshot") cmdparser.add_option("--noimages", action="store_true", help="don't load images") cmdparser.add_option("--debug", action="store_true", help=optparse.SUPPRESS_HELP) (options, args) = cmdparser.parse_args() if len(args) == 0: cmdparser.print_usage() return if options.filename: if len(args) != 1 or args[0] == "-": print "--filename option requires exactly one url" sys.stdout.flush() return if options.scale == 0: cmdparser.error("scale cannot be zero") # make sure we're outputing something if not (options.fullsize or options.thumb or options.clipped): options.fullsize = True options.thumb = True options.clipped = True # work out the initial size of the browser window # (this might need to be larger so clipped image is right size) options.initWidth = (options.clipwidth / options.scale) options.initHeight = (options.clipheight / options.scale) if options.width>options.initWidth: options.initWidth = options.width if options.height>options.initHeight: options.initHeight = options.height app = AppKit.NSApplication.sharedApplication() # create an app delegate delegate = AppDelegate.alloc().init() AppKit.NSApp().setDelegate_(delegate) # create a window rect = Foundation.NSMakeRect(0,0,100,100) win = AppKit.NSWindow.alloc() win.initWithContentRect_styleMask_backing_defer_ (rect, AppKit.NSBorderlessWindowMask, 2, 0) if options.debug: win.orderFrontRegardless() # create a webview object webview = WebKit.WebView.alloc() webview.initWithFrame_(rect) # turn off scrolling so the content is actually x wide and not x-15 webview.mainFrame().frameView().setAllowsScrolling_(objc.NO) webview.setPreferencesIdentifier_('webkit2png') webview.preferences().setLoadsImagesAutomatically_(not options.noimages) # add the webview to the window win.setContentView_(webview) # create a LoadDelegate loaddelegate = WebkitLoad.alloc().init() loaddelegate.options = options loaddelegate.urls = args webview.setFrameLoadDelegate_(loaddelegate) app.run() if __name__ == '__main__' : main() Best, James -------------- next part -------------- An HTML attachment was scrubbed... URL: