pywebview
pywebview copied to clipboard
Open Custom File Extension (MacOS CFBundleTypeExtensions)
Specification
- pywebview version: 3.3.1
- platform / version: macOS 0.15.5 and Windows 10
Description
First off. This is an amazing project. Thank you for creating pywebview!!
An event handler for when a file is opened for a specific file extension/type in macOS I believe it's CFBundleTypeExtensions in the plist. I'm able to get pywebview to open using this setting but unable to handle the file being opened. Here's the plist argument I'm passing in setup.py:
OPTIONS = {..
'plist': {
'CFBundleName': "MyApp",
'CFBundleDisplayName': "MyApp",
'CFBundleGetInfoString': "App it Up",
'CFBundleIdentifier': "com.example.app",
'CFBundleVersion': "0.1.0",
"CFBundleTypeRole": "editor",
"CFBundleTypeExtensions": ["appy-mc-apperson"],
'CFBundleShortVersionString': "0.1.0",
'NSHumanReadableCopyright': u"Copyright © 2020, Justin Mitchel, All Rights Reserved"
}
}
The appy-mc-apperson represents something like my-project.appy-mc-apperson to, ideally, re-open our application and re-load the project. For context, .appy-mc-apperson is an arbitrary extension I made up for this post.
This works in Electron fairly simply as you can see here under fileAssociations. This would allow pywebview apps to resume projects that are being worked on which would be key for several projects I'm working on.
Practicalities
-YES. Happy to help however I can. -YES. I am prepared to support this issue financially within reason of course. I'm trying not to use Electron as much since it's so bloated especially for tiny projects.
I am not familiar with this API, but this definitely should be implemented.
Without dwelling into details, I believe an appropriate event handler should be added to cocoa.py. Other platforms should be investigated as well.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
@jmitchel3 can you explain more
I wanted to add an update here based on something that's nearly working with py2app configuration.
OPTIONS = {
"argv_emulation": True,
...
"plist": {
'CFBundleName': "MyApp",
'CFBundleDisplayName': "MyApp",
'CFBundleGetInfoString': "App it Up",
'CFBundleIdentifier': "com.example.app",
'CFBundleVersion': "0.1.0",
"CFBundleTypeRole": "Editor",
"CFBundleTypeExtensions": ["appy-mc-apperson"],
"CFBundleTypeIconFile": "icon.icns",
'CFBundleShortVersionString': "0.1.0",
'NSHumanReadableCopyright': u"Copyright © 2020, Justin Mitchel, All Rights Reserved"
},
}
Once you have "argv_emulation": True, the rest of your code will have access to another argument in sys.argv.
When you open your file extension, in this case I called it appy-mc-apperson which means if I double click my-project.appy-mc-apperson I see the following:

Once you select your pywebview built app, my-project.appy-mc-apperson will always open your app with a new argument in sys.argv:
print(sys.argv[1])
# prints path/to/system/location/of/my-project.appy-mc-apperson
This sys.argv[1], if available, is a path to the my-project.appy-mc-apperson file. You can read this file as needed in your pywebview project.
If your app is not open, it works! (without changes to cocoa.py). However, f your app is open and you double-click to open an associated file you'll see this error:
.
I'd guess that pyinstaller might have a different way of implementing this same idea. It stands to reason that when you open any file on your system, the OS will open the application with an argument for that file path.
I think we still need to solve:
- Errors on multiple file opening
- Automatic system-wide file association on app opening
- Cross platform support
- Simple menu support (including
cmd+oandcmd+s)
For anyone that stumbles upon this issue, you can solve the above issue by following these three steps:
- Switch to the
webview.start(gui='qt')engine, as it's more configurable. - Turn off
argv_emulation. Rely on the qt engine's event handling instead of py2app's event handling. - Add an event handler to webview's qt engine, similar to this SO answer.
Here's a minimal change to the hello world pywebview script that shows the idea.
app.py
import webview
import webview.platforms.qt
from qtpy.QtWidgets import QApplication
from qtpy.QtCore import QEvent
import webview.platforms.qt # needed for us to define a custom application
class MainApplication(QApplication):
def event(self, event: QEvent):
if event.type() == QEvent.Type.FileOpen:
print(event.url())
return super().event(event)
if __name__ == '__main__':
app = MainApplication([]) # so that when pywebview calls `QApplication.instance()` your app is returned
webview.create_window('Hello world', 'https://pywebview.flowrl.com/')
webview.start(gui='qt')
setup.py
"""Simple setup script for actually building your application. See README"""
from setuptools import setup
APP = ['app.py'] # your main application
OPTIONS = {
'plist': {
'CFBundleURLTypes': [
{
'CFBundleURLName': 'MyApplication',
'CFBundleURLSchemes': ['myapp'],
},
],
},
'strip': True,
'includes': ['WebKit', 'Foundation', 'webview'],
}
setup(
app=APP,
options={'py2app': OPTIONS},
setup_requires=['py2app', 'pyqt6'], # add other dependencies here
)