cork

Package web apps for the terminal. Based on PyInstaller and bad intentions.


License
GPL-3.0+
Install
pip install cork==0.2

Documentation

screenshot.png

Cork

Take a Flask web application and create a stand-alone terminal application. "Inspired" by Electron.js.

Created during a silly/useless tech hackathon at a place called the the Recurse Center. It is mostly my fault, but @thechutrain helped too.

Extreme alpha stages. I have only run this on a single computer (Linux with Python 3.7). Please do use it, but don't use it, you know?

Installation

pip install cork

This is published in the official Python Packaging Index. Good jokes are about commitment.

Quickstart

Cork is a utility that will produce a standalone executable from your Flask app. All you have to do is point it at a Python module with a valid Flask (app) object.

If your Flask application lived in a module called example, you could run this command:

cork bundle example

This will produce a ./dist directory with an executable ./dist/example and the application dependencies (static files, templates, etc) bundled into ./dist/bundle. You can distribute the contents of the ./dist directory to end users. The bundled dependencies directory will get moved out of the way when a user first runs the ./dist/example executable.

To see the demo, you can run cork bundle demo.

Commands

cork bundle [source] Create an executable from the source module. Can be used with the following flags:

-c, --cleanup Remove the corkfile and PyInstaller artifacts after creating the executable. -f, --force Overwrites any existing corkfile. -b, --browser Set the terminal browser used to view the application. Defaults to browsh. -a, --app Define the name of the Flask app object to be imported from the source module. Defaults to app. -p, --port Set the default port to try launching the Flask app server on. Defaults to 5000. If the specified port is in use by another process, Cork applications increment by 1 until an open port is found. --teardown-route Set the name of the special route that Cork application bind to the Flask app to allow for shutting down the Flask application server at quit time. Defaults to teardown. --teardown-function Sets the name of the function that will decorated for the --teardown-route outlined above. Defaults to teardown.

cork cleanup Remove artifacts left behind by the Cork and PyInstaller processes. By default, will delete th e corkfile and the PyInstaller build and any .spec files. The dist directory (with the Cork executable and dependency folder) is retained by default. Can be used with the following flags:

-t, --target Only remove .spec files associated with the specified cork application. -f, --force Avoid confirmation prompt, go straight to deleting the files. -d, --dist Delete the dist directory as well as the default files.

How It Bundles

When running cork bundle:

  • Cork creates a wrapper script for managing dependencies and running the application. This wrapper scrapped is called a corkfile.
  • PyInstaller is called on this corkfile to create a single executable file out of this wrapper script.
  • Non-Python file dependencies are collected into a single bundle directory and placed next to the executable PyInstaller created.

The main function of the corkfile script is to run a Flask application in a separate thread, then call a terminal browser to view it. A special teardown route is added to the Flask app so that when the user ends their browser session, the Flask application can be shut down instead of running until it is force-quit. The corkfile also handles the details of handling the file dependencies that cannot be placed into the executable itself.

PyInstaller packages up the Python interpereter and library dependencies into a single file executable. It places the executable in the ./dist directory.

cork places your web app files and a copy of a terminal browser (defaults to browsh) into the dist/bundle directory. The web app files need to be shipped with the application so that static files, template files, etc are accessible on the target system. The browser is shipped so that the user does not need to have it already installed.

When the user first runs the application, this bundle folder of dependencies will get moved out of the way into the user's home config directory. If the XDG_CONFIG_HOME env variable is set, this value will be respected, otherwise it will default to ~HOME/.config. All Cork applications installed on a system share the same browser binaries (stored in ~/.config/cork/browsers). The web app files are stored in ~/.config/cork/<app_name>, and that directory is added o the front of the system path so that Python looks there first for library imports.

A side-effect of this is that no two Cork applications can share a name on the same system, since there can only be one ~/.config/cork/<app_name>. Cork applications will silently remove existing conflicting directories the first time they are run, and replace them with the dependencies they are shipped with.

Development

Uses pytest for running the tests. After installing requirements.txt in your environment you should be able to run pytest from the root directory of this repo.

If I ever work on this in the future I would want to add support for other Python web app frameworks, especially Django, and other terminal-based browsers, especially Lynx.

Pull requests and so on are encouraged. If you think this is fun/funny, go ahead and reach out!