mirror of https://github.com/chriskiehl/Gooey.git
Kiehl
5 years ago
committed by
Chris
5 changed files with 488 additions and 0 deletions
Split View
Diff Options
-
92docs/Other-Languages.md
-
68docs/packaging/Packaging-Custom-Images.md
-
146docs/packaging/Packaging-Gooey.md
-
56docs/packaging/build.spec
-
126docs/releases/1.0.3-release-notes.md
@ -0,0 +1,92 @@ |
|||
# Using Gooey as a frontend for any language. |
|||
|
|||
Gooey can be used as the frontend for _any_ language. Whether you've built your application in Java, Node, or Haskell, Gooey can still be used to create a fast, free UI with just a little bit of Python. |
|||
|
|||
|
|||
|
|||
|
|||
Gooey let's you specify the `target` that is should execute during runtime as an argument to the main decorator. |
|||
|
|||
|
|||
|
|||
Clojure example: |
|||
|
|||
``` |
|||
lein new app clojure-program |
|||
``` |
|||
|
|||
|
|||
``` |
|||
(ns clojure-program.core |
|||
(:gen-class)) |
|||
|
|||
(defn -main |
|||
"Tiny example." |
|||
[& args] |
|||
(println "here are the args: " args) |
|||
(doseq [x (range 10)] |
|||
(println x) |
|||
(Thread/sleep 500))) |
|||
``` |
|||
|
|||
``` |
|||
lein uberjar |
|||
``` |
|||
|
|||
``` |
|||
./target/uberjar/clojure-program-0.1.0-SNAPSHOT-standalone.jar |
|||
``` |
|||
|
|||
``` |
|||
java -jar target/uberjar/clojure-program-0.1.0-SNAPSHOT-standalone.jar -arg1 foo -arg2 bar |
|||
``` |
|||
|
|||
``` |
|||
here are the args: (-f foo -b qwer) |
|||
0 |
|||
1 |
|||
2 |
|||
3 |
|||
etc... |
|||
``` |
|||
|
|||
|
|||
|
|||
|
|||
``` |
|||
mkdir clojure-ui-example |
|||
cd clojure-ui-example |
|||
``` |
|||
|
|||
``` |
|||
virtualenv venv |
|||
pip install gooey |
|||
``` |
|||
|
|||
``` |
|||
mkdir resources |
|||
``` |
|||
|
|||
|
|||
src/main.py |
|||
``` |
|||
from gooey import Gooey, GooeyParser, local_resource_path |
|||
|
|||
|
|||
jar_path = local_resource_path('resources/clojure-gooey-0.1.0-SNAPSHOT-standalone.jar') |
|||
|
|||
@Gooey(image_dir=local_resource_path('stuff/images/'), target='java -jar ' + jar_path) |
|||
def main(): |
|||
parser = GooeyParser(description="My program") |
|||
parser.add_argument('filename', metavar='Filename', help='filename', widget='FileChooser') |
|||
parser.parse_args() |
|||
|
|||
|
|||
if __name__ == '__main__': |
|||
main() |
|||
``` |
|||
|
|||
|
|||
|
|||
|
|||
|
@ -0,0 +1,68 @@ |
|||
# Using Custom Images while Packaging |
|||
|
|||
> Note: if you're new to packaging Gooey, checkout the main Packaging guides first! |
|||
|
|||
Gooey comes with a set of six default icons. These can be overridden with your own custom images/icons by telling Gooey to search additional directories when initializing. This is done via the `image_dir` argument to the `Gooey` decorator. |
|||
|
|||
```python |
|||
@Gooey(program_name='Custom icon demo', image_dir='/path/to/images') |
|||
def main(): |
|||
# rest of program |
|||
``` |
|||
|
|||
While this works for regular executions, a little additional work is required to make sure that your images will actually be available when running as a stand alone executable. |
|||
|
|||
To make your custom images available after packaging, you have to do two things. |
|||
|
|||
**Step 1:** wrap the path to your image directory in the `local_resource_path()` function provided by Gooey. This will handle the logic of resolving the base directory in which PyInstaller unpacks your resources. |
|||
|
|||
```python |
|||
from gooey import Gooey, local_resource_path |
|||
|
|||
@Gooey(image_dir=local_resource_path('relative/path/to/images')) |
|||
def main(): |
|||
... |
|||
``` |
|||
|
|||
**Step 2:** Update `build.spec` to include the image directory during bundling. This is done by giving the path to your Images as a Tree object to Pyinstaller's `EXE` section. |
|||
|
|||
``` |
|||
# -*- mode: python ; coding: utf-8 -*- |
|||
|
|||
import os |
|||
... |
|||
gooey_images = Tree(os.path.join(gooey_root, 'images'), prefix = 'gooey/images') |
|||
|
|||
# LOOK AT ME! I AM A TREE OBJECT |
|||
image_overrides = Tree('path/to/images', prefix='path/to/images') |
|||
|
|||
... |
|||
|
|||
exe = EXE(pyz, |
|||
a.scripts, |
|||
a.binaries, |
|||
a.zipfiles, |
|||
a.datas, |
|||
options, |
|||
gooey_languages, |
|||
gooey_images, |
|||
image_overrides, # <-- NEW |
|||
name='APPNAME', |
|||
debug=False, |
|||
strip=None, |
|||
upx=True, |
|||
console=False, |
|||
icon=os.path.join(gooey_root, 'images', 'program_icon.ico')) |
|||
``` |
|||
|
|||
And then build via PyInstaller as usual. |
|||
|
|||
``` |
|||
pyinstaller build.spec |
|||
``` |
|||
|
|||
PyInstaller will now include your images in its bundle. |
|||
|
|||
|
|||
|
|||
|
@ -0,0 +1,146 @@ |
|||
# Packaging Gooey as a Stand Alone Application |
|||
|
|||
>:warning: Packaging Gooey is an ongoing science. Gooey currently runs on all the major platforms, can be installed in a bajillion different ways, and has several active versions in wide usage. In short, edge cases abound. If you run into any problems, [this issue0(https://github.com/chriskiehl/Gooey/issues/259) is a great place to dump whatever errors you're running into. Just be sure to give as many details about your setup, what you've tried, and the errors you're seeing! |
|||
|
|||
>Instructions tested against Gooey 1.0.3 and pyinstaller 3.5 on Mojave 10.14.6 |
|||
|
|||
>This is all made possible by the work from @john174586, @jrjhealey's, and the research of numerous others. |
|||
|
|||
>Pull requests with additional steps and packaging information are highly welcome. |
|||
|
|||
Packing Gooey into a standalone executable is super straight forward thanks to [PyInstaller](http://www.pyinstaller.org/). It is the only dependency you'll need and can be installed via the following. |
|||
|
|||
``` |
|||
pip install pyinstaller |
|||
``` |
|||
|
|||
**Setting up the build instructions:** |
|||
|
|||
PyInstaller uses [spec files](http://pythonhosted.org/PyInstaller/#using-spec-files) to determine how to bundle the project. These are a bit like `setup.py` files, but contain rules for how PyInstaller should bundle your whole application as a stand alone executable. |
|||
|
|||
>Note: if you're still rocking Python 2.7, see [the Python2.7 section at the bottom for a few additional steps](#Python-2.7). |
|||
|
|||
These provide a list of directives on how to build the package, setup hooks to run, and resources to include. |
|||
|
|||
This file should be placed in the root of your project. |
|||
|
|||
e.g. |
|||
|
|||
``` |
|||
MyProject/ |
|||
- src/ |
|||
- build.spec # <-- goes here! |
|||
- LICENCE.txt |
|||
- README.md |
|||
``` |
|||
|
|||
You can grab a pre-built spec file [here](TODO), or create a `build.spec` by hand in the root directory of your project and paste in the following: |
|||
|
|||
``` |
|||
# -*- mode: python ; coding: utf-8 -*- |
|||
|
|||
import os |
|||
import platform |
|||
import gooey |
|||
gooey_root = os.path.dirname(gooey.__file__) |
|||
gooey_languages = Tree(os.path.join(gooey_root, 'languages'), prefix = 'gooey/languages') |
|||
gooey_images = Tree(os.path.join(gooey_root, 'images'), prefix = 'gooey/images') |
|||
|
|||
from PyInstaller.building.api import EXE, PYZ, COLLECT |
|||
from PyInstaller.building.build_main import Analysis |
|||
from PyInstaller.building.datastruct import Tree |
|||
from PyInstaller.building.osx import BUNDLE |
|||
|
|||
block_cipher = None |
|||
|
|||
a = Analysis(['APPNAME.py'], # replace me with the app name |
|||
pathex=['/path/to/APP.py'], # replace me with the appropriate path |
|||
hiddenimports=[], |
|||
hookspath=None, |
|||
runtime_hooks=None, |
|||
) |
|||
pyz = PYZ(a.pure) |
|||
|
|||
options = [('u', None, 'OPTION'), ('v', None, 'OPTION'), ('w', None, 'OPTION')] |
|||
|
|||
|
|||
exe = EXE(pyz, |
|||
a.scripts, |
|||
a.binaries, |
|||
a.zipfiles, |
|||
a.datas, |
|||
options, |
|||
gooey_languages, |
|||
gooey_images, |
|||
name='APPNAME', # FIXME |
|||
debug=False, |
|||
strip=None, |
|||
upx=True, |
|||
console=False, |
|||
icon=os.path.join(gooey_root, 'images', 'program_icon.ico')) |
|||
|
|||
if platform.system() == 'Darwin': |
|||
info_plist = {'addition_prop': 'additional_value'} |
|||
app = BUNDLE(exe, |
|||
name='APPNAME.app', |
|||
bundle_identifier=None, |
|||
info_plist=info_plist |
|||
) |
|||
``` |
|||
|
|||
This is the standard `build.spec` generated by Pyinstaller, but with a few additions to ensure that all of Gooey's assets get pulled in correctly during bundling. |
|||
|
|||
|
|||
From this spec, you'll need to make two tweaks. |
|||
|
|||
1. replace `APPNAME` in the `Analysis()` section with the name of _your_ application |
|||
2. replace the `pathex` value in the `Analysis()` section with the path to your application's root |
|||
|
|||
> note: If you use additional data resources (e.g. images, data, etc..) you'll also need to explicitly add them to the EXE section. See [packaging custom images] for more info. |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
**Windows Notes** |
|||
|
|||
|
|||
**OSX Notes:** |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
### Python 2.7 |
|||
|
|||
If you're on Python 2.7, you'll need to make one addition to your source file to ensure smooth output for Gooey. By default, the python interpreter will aggressively buffer stdout which means that rather than Gooey being able to read and display the output of your program in real time, it receives it in awkward coarsely grained chunks. |
|||
|
|||
Normally, passing the -u flag to the Python interpreter would be enough to prevent stdout buffering. However, due to an apparent quirk in PyInstaller, it seems that the -u flag never makes its way up to the interpreter, and thus the output is still highly buffered. Luckily, getting around this pretty easy. |
|||
|
|||
Add these two lines to your source anywhere before your main() (or equivalent) method. |
|||
|
|||
nonbuffered_stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) |
|||
sys.stdout = nonbuffered_stdout |
|||
|
|||
### Troubleshooting |
|||
|
|||
|
|||
**Exception: This program needs access to the screen. Please run with a Framework build of python, and only when you are logged in on the main display of your Mac.** |
|||
|
|||
This happens on OSX when you neglect the `--windowed` flag during your build step. |
|||
|
|||
wrong: |
|||
``` |
|||
pyinstaller build.spec ## oops! forgot the required flags |
|||
``` |
|||
|
|||
Correct: |
|||
``` |
|||
pyinstaller --windowed build.spec |
|||
``` |
|||
|
|||
Checkout the [Pyinstaller Manual](https://github.com/pyinstaller/pyinstaller/wiki/FAQ) for more details. |
@ -0,0 +1,56 @@ |
|||
# -*- mode: python ; coding: utf-8 -*- |
|||
""" |
|||
Example build.spec file |
|||
|
|||
This hits most of the major notes required for |
|||
building a stand alone version of your Gooey application. |
|||
""" |
|||
|
|||
|
|||
import os |
|||
import platform |
|||
import gooey |
|||
gooey_root = os.path.dirname(gooey.__file__) |
|||
gooey_languages = Tree(os.path.join(gooey_root, 'languages'), prefix = 'gooey/languages') |
|||
gooey_images = Tree(os.path.join(gooey_root, 'images'), prefix = 'gooey/images') |
|||
|
|||
from PyInstaller.building.api import EXE, PYZ, COLLECT |
|||
from PyInstaller.building.build_main import Analysis |
|||
from PyInstaller.building.datastruct import Tree |
|||
from PyInstaller.building.osx import BUNDLE |
|||
|
|||
block_cipher = None |
|||
|
|||
a = Analysis(['APPNAME.py'], # replace me with your path |
|||
pathex=['/path/to/APP.py'], |
|||
hiddenimports=[], |
|||
hookspath=None, |
|||
runtime_hooks=None, |
|||
) |
|||
pyz = PYZ(a.pure) |
|||
|
|||
options = [('u', None, 'OPTION'), ('v', None, 'OPTION'), ('w', None, 'OPTION')] |
|||
|
|||
|
|||
exe = EXE(pyz, |
|||
a.scripts, |
|||
a.binaries, |
|||
a.zipfiles, |
|||
a.datas, |
|||
options, |
|||
gooey_languages, |
|||
gooey_images, |
|||
name='APPNAME', |
|||
debug=False, |
|||
strip=None, |
|||
upx=True, |
|||
console=False, |
|||
icon=os.path.join(gooey_root, 'images', 'program_icon.ico')) |
|||
|
|||
if platform.system() == 'Darwin': |
|||
info_plist = {'addition_prop': 'additional_value'} |
|||
app = BUNDLE(exe, |
|||
name='APPNAME.app', |
|||
bundle_identifier=None, |
|||
info_plist=info_plist |
|||
) |
@ -0,0 +1,126 @@ |
|||
# Gooey 1.0.3 Released! |
|||
|
|||
|
|||
After cooking for far too long, **Gooey 1.0.3 is released!** |
|||
|
|||
|
|||
|
|||
Grab the latest version: |
|||
|
|||
|
|||
|
|||
* [github](https://github.com/chriskiehl/Gooey) |
|||
* [PyPi](TODO) |
|||
|
|||
|
|||
|
|||
Runnable demos for all the new features can be found in the [Examples repo](https://github.com/chriskiehl/GooeyExamples). |
|||
|
|||
## Overview: |
|||
|
|||
|
|||
A lot of focus was put on settling Gooey into a more mature stable project. I've spent a lot of time writing documentation, stamping down cross platform issues / quirks, and making numerous tweaks and additions to enable a smoother experience when packaging Gooey powered application for distribution. |
|||
|
|||
|
|||
## What's new |
|||
|
|||
New logo |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
### Fancy Layout controls! |
|||
|
|||
|
|||
|
|||
![image@735,612,489,366,243,120+jpeg](https://s3.amazonaws.com/awsblogstore/articles/da7760ce/7c0a2945-image) |
|||
|
|||
|
|||
|
|||
The main goal of this release was enabling more complex real-world layouts and more customization of Gooey's UI. As of 1.1.0, you now have have control over every color, font, and display status within the application. You can now brand Gooey to your organization's colors, logically group related items under a central heading, and optionally show/hide all the individual components that make up an input widget. |
|||
|
|||
|
|||
### Menu Bars |
|||
|
|||
Gooey now includes a simple declarative system for creating top level menu bars and items. |
|||
|
|||
![image@681,567,453,339,225,111+jpeg](https://s3.amazonaws.com/awsblogstore/articles/da7760ce/0c14f2dd-image) |
|||
|
|||
|
|||
|
|||
The menu option currently supports three flavors: |
|||
|
|||
|
|||
|
|||
**AboutDialog** |
|||
|
|||
|
|||
This is an AboutDialog as rendered natively by your OS. It's a good place to show standard info like version info, descriptions, licenses, etc.. in a standard way across platforms. |
|||
|
|||
|
|||
|
|||
**MessageDialogs** |
|||
|
|||
|
|||
Next up are general message dialogs. You can display any informational text inside of these. |
|||
|
|||
|
|||
|
|||
**Link** |
|||
|
|||
|
|||
|
|||
Finally, you can create fixed menu items that simply link to external resources, for instance, your site, documentation, pdfs, etc.. |
|||
|
|||
|
|||
## Rich Text Controls |
|||
|
|||
Thanks to @NathanRichard, Gooey can now optionally honor terminal control sequences and display Rich Text in the output panel. |
|||
|
|||
![image@608,506,404,302,200,98+jpeg](https://s3.amazonaws.com/awsblogstore/articles/da7760ce/a0f11901-image) |
|||
|
|||
|
|||
## Additional features |
|||
|
|||
* OSX now shows program Icon in Dock |
|||
* `show_error_modal` option to toggle whether or not failures additionally raise alert modals. |
|||
* `BlockCheckbox` widget. |
|||
* Hyperlinks written to the console appear as such and will launch a browser on click |
|||
* `clear_before_run` option lets you control whether or not subsequent program runs start from a fresh terminal or preserve the previous output. |
|||
* Conditionally show/hide restart button |
|||
* `requires_shell` option - controls how `Popen` spawns your program. By default (and historically), this value is False. |
|||
* Optionally silence textual progress updates when using the Progress widget (via @conradhilley) |
|||
* Multi-Directory Choosers - these were accidentally dropped from the project. @HenrykHaniewicz added them back! |
|||
* Additional explicit wx imports to make packaging on OSX easier |
|||
* Textfields can now be made Readonly for informational purposes |
|||
|
|||
|
|||
|
|||
|
|||
## Breaking Changes |
|||
|
|||
No breaking changes between `1.0.0` and `1.1.0`! |
|||
|
|||
## Language Additions / Improvements |
|||
|
|||
* Completed Italian translation - @gison93 |
|||
|
|||
* Updated French translation - @NathanRichard |
|||
* Updated Hebrew translation - @eturkes |
|||
|
|||
|
|||
|
|||
## Bug Fixes |
|||
|
|||
* Fixed 5 year old bug(!) where an errant lambda function wasn't passing through all of its arguments which caused frustratingly opaque failures under specific conditions. |
|||
* Fixed bug where external updates weren't applied to `ListBox` |
|||
* Fix bug where tuples weren't coerced to List which causes concatenation errors |
|||
* Fixed bug where string coercion in `argparse_to_json` was too broad and caused type errors |
|||
* Fixed bug where wrong validator was applied to Dropdown type causing preflight checks to always fail |
|||
* Fixed bug where Radio Groups would apply too much vertical spacing between components |
|||
* Fixed bug where subgroups with single items were attached to the wrong UI parent |
|||
* Fixed bug where legacy default groups weren't being translated |
|||
* Fixed bug where certain languages would sometimes cause components to be rendered off screen |
|||
|
|||
|
Write
Preview
Loading…
Cancel
Save