Skip to content

Commit eee4945

Browse files
committed
inital commit
0 parents  commit eee4945

File tree

10 files changed

+279
-0
lines changed

10 files changed

+279
-0
lines changed

.travis.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
os: osx
2+
sudo: required
3+
language: generic
4+
5+
install:
6+
- "./build.sh"

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# PythonDotApp
2+
3+
Skeleton to build Python 3 together with a custom hello world application and package it as OS X Application.
4+
5+
Before you start, install brew.
6+
7+
To install additional packages add them to requirements.txt
8+
9+
If you need more packages from brew you have to edit build.sh

build.sh

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
#!/bin/bash
2+
set -e
3+
4+
NAME="PythonSkeleton"
5+
IDENTIFIER="com.example.PythonSkeleton"
6+
OSXVERSION=10.9
7+
APPLICATION=application
8+
9+
BASE=`pwd`
10+
PREFIX="$BASE/dist"
11+
BREW=/usr/local
12+
13+
brew update
14+
15+
function brew_install {
16+
pkg=$1
17+
brew list | grep -q $pkg || brew install $pkg
18+
brew outdated $pkg || brew upgrade $pkg
19+
}
20+
21+
brew_install openssl
22+
brew_install sqlite
23+
brew_install xz
24+
brew_install readline
25+
26+
# add lxml dependencies
27+
brew_install libxml2
28+
brew_install libxslt
29+
30+
# Python
31+
CPPFLAGS="-I$BREW/opt/openssl/include/openssl"
32+
LDFLAGS=""
33+
for pkg in openssl sqlite readline xz; do
34+
CPPFLAGS="$CPPFLAGS -I$BREW/opt/$pkg/include"
35+
LDFLAGS="$LDFLAGS -L$BREW/opt/$pkg/lib"
36+
done
37+
export CPPFLAGS
38+
export LDFLAGS
39+
40+
version=3.5.2
41+
url="https://www.python.org/ftp/python/${version}/Python-${version}.tar.xz"
42+
name=`basename $url .tar.xz`
43+
tar=`basename $url`
44+
45+
test -e $tar || curl -O $url
46+
test -e $name || tar xf $tar
47+
cd $name
48+
./configure MACOSX_DEPLOYMENT_TARGET=$OSXVERSION --prefix="$PREFIX"
49+
make -j8
50+
make altinstall
51+
52+
unset CPPFLAGS
53+
unset LDFLAGS
54+
55+
ln -sf pip3.5 "$PREFIX/bin/pip"
56+
ln -sf pip3.5 "$PREFIX/bin/pip3"
57+
ln -sf python3.5 "$PREFIX/bin/python3"
58+
59+
60+
PATH="$PREFIX/bin:$PATH"
61+
cd "$BASE"
62+
test -e requirements.txt && pip3.5 install -r requirements.txt
63+
64+
chmod -R +rw "$PREFIX/lib"
65+
# make self contained
66+
for lib in \
67+
opt/libxml2/lib/libxml2.2.dylib \
68+
opt/libxslt/lib/libexslt.0.dylib \
69+
opt/libxslt/lib/libxslt.1.dylib \
70+
opt/openssl/lib/libcrypto.1.0.0.dylib \
71+
opt/openssl/lib/libssl.1.0.0.dylib \
72+
opt/readline/lib/libreadline.6.dylib \
73+
opt/sqlite/lib/libsqlite3.0.dylib \
74+
opt/xz/lib/liblzma.5.dylib \
75+
; do
76+
target="$PREFIX/lib/`basename "$lib"`"
77+
rm -f "$target"
78+
cp -a "$BREW/$lib" "$target"
79+
done
80+
chmod -R +rw "$PREFIX/lib"
81+
mkdir -p "$PREFIX/etc/openssl/certs"
82+
cp /usr/local/etc/openssl/cert.pem "$PREFIX/etc/openssl"
83+
84+
# cleanup
85+
rm -rf \
86+
"$PREFIX/lib/python3.5/test" \
87+
"$PREFIX/bin/openssl" \
88+
"$PREFIX/etc/openssl/man" \
89+
"$PREFIX/bin/c_rehash" \
90+
"$PREFIX/bin/2to3-3.5" \
91+
"$PREFIX/bin/easy_install-3.5" \
92+
"$PREFIX/bin/idle3.5" \
93+
"$PREFIX/bin/pyvenv-3.5" \
94+
"$PREFIX/bin/c_rehash" \
95+
"$PREFIX/bin/pydoc3.5"
96+
97+
for bin in $PREFIX/bin/pip3.5 $PREFIX/bin/python3.5m-config; do
98+
sed "s#$PREFIX/bin/python3.5#/usr/bin/env python3.5#g" "$bin" > "$bin.t"
99+
mv "$bin.t" "$bin"
100+
chmod +x "$bin"
101+
done
102+
103+
find "$PREFIX" -d -name "__pycache__" -type d -exec rm -r "{}" \;
104+
find "$PREFIX" -name "*.pyc" -exec rm "{}" \;
105+
find "$PREFIX" -name "*.a" -exec rm -f "{}" \;
106+
107+
for plib in \
108+
$PREFIX/lib/python3.5/site-packages/lxml/etree.cpython-35m-darwin.so \
109+
$PREFIX/lib/python3.5/site-packages/lxml/objectify.cpython-35m-darwin.so \
110+
$PREFIX/lib/python3.5/lib-dynload/_hashlib.cpython-35m-darwin.so \
111+
$PREFIX/lib/python3.5/lib-dynload/_lzma.cpython-35m-darwin.so \
112+
$PREFIX/lib/python3.5/lib-dynload/_sqlite3.cpython-35m-darwin.so \
113+
$PREFIX/lib/python3.5/lib-dynload/_ssl.cpython-35m-darwin.so \
114+
$PREFIX/lib/python3.5/lib-dynload/readline.cpython-35m-darwin.so \
115+
; do
116+
if [ -e "$plib" ]; then
117+
for lib in \
118+
$BREW/Cellar/libxslt/1.1.28_1/lib/libxslt.1.dylib \
119+
$BREW/Cellar/openssl/1.0.2d_1/lib/libcrypto.1.0.0.dylib \
120+
$BREW/opt/libxml2/lib/libxml2.2.dylib \
121+
$BREW/opt/libxslt/lib/libexslt.0.dylib \
122+
$BREW/opt/libxslt/lib/libxslt.1.dylib \
123+
$BREW/opt/openssl/lib/libcrypto.1.0.0.dylib \
124+
$BREW/opt/openssl/lib/libssl.1.0.0.dylib \
125+
$BREW/opt/readline/lib/libreadline.6.dylib \
126+
$BREW/opt/sqlite/lib/libsqlite3.0.dylib \
127+
$BREW/opt/xz/lib/liblzma.5.dylib \
128+
$PREFIX/lib/libcrypto.1.0.0.dylib \
129+
$PREFIX/lib/libexslt.0.dylib \
130+
$PREFIX/lib/liblzma.5.dylib \
131+
$PREFIX/lib/libreadline.6.dylib \
132+
$PREFIX/lib/libsqlite3.0.dylib \
133+
$PREFIX/lib/libssl.1.0.0.dylib \
134+
$PREFIX/lib/libxml2.2.dylib \
135+
$PREFIX/lib/libxslt.1.dylib \
136+
/usr/lib/libexslt.0.dylib \
137+
/usr/lib/libreadline.6.dylib \
138+
/usr/lib/libxml2.2.dylib \
139+
/usr/lib/libxslt.1.dylib \
140+
; do
141+
name=`basename $lib`
142+
otool -L "$plib" | grep -q "$lib" && install_name_tool -change "$lib" "@executable_path/../lib/$name" "$plib"
143+
done
144+
otool -L "$plib"
145+
fi
146+
done
147+
148+
mkdir -p "${NAME}.app/Contents/MacOS"
149+
mv $PREFIX "${NAME}.app/Contents/Python"
150+
cat > "$NAME.app/Contents/MacOS/$NAME" << EOF
151+
#!/bin/bash
152+
cd "\$(dirname "\$0")"
153+
PREFIX="\$(dirname "\$(pwd)")/Python"
154+
export SSL_CERT_FILE="\$PREFIX/etc/openssl/cert.pem"
155+
export SSL_CERT_DIR="\$PREFIX/etc/openssl/certs"
156+
"\$PREFIX/bin/python3.5" -m $APPLICATION
157+
EOF
158+
chmod +x "$NAME.app/Contents/MacOS/$NAME"
159+
160+
cat > "$NAME.app/Contents/Info.plist" << EOF
161+
<?xml version="1.0" encoding="UTF-8"?>
162+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
163+
<plist version="1.0">
164+
<dict>
165+
<key>BuildMachineOSBuild</key>
166+
<string>15C50</string>
167+
<key>CFBundleDevelopmentRegion</key>
168+
<string>en</string>
169+
<key>CFBundleExecutable</key>
170+
<string>${NAME}</string>
171+
<key>CFBundleIconFile</key>
172+
<string>AppIcon</string>
173+
<key>CFBundleIdentifier</key>
174+
<string>${IDENTIFIER}</string>
175+
<key>CFBundleInfoDictionaryVersion</key>
176+
<string>6.0</string>
177+
<key>CFBundleName</key>
178+
<string>${NAME}</string>
179+
<key>CFBundlePackageType</key>
180+
<string>APPL</string>
181+
<key>CFBundleShortVersionString</key>
182+
<string>0.8</string>
183+
<key>CFBundleSignature</key>
184+
<string>????</string>
185+
<key>CFBundleSupportedPlatforms</key>
186+
<array>
187+
<string>MacOSX</string>
188+
</array>
189+
<key>CFBundleVersion</key>
190+
<string>1</string>
191+
<key>DTPlatformBuild</key>
192+
<string>7C68</string>
193+
<key>DTPlatformVersion</key>
194+
<string>GM</string>
195+
<key>DTSDKBuild</key>
196+
<string>15C43</string>
197+
<key>DTSDKName</key>
198+
<string>macosx10.10</string>
199+
<key>DTXcode</key>
200+
<string>0720</string>
201+
<key>DTXcodeBuild</key>
202+
<string>7C68</string>
203+
<key>LSMinimumSystemVersion</key>
204+
<string>${OSXVERSION}</string>
205+
<key>LSUIElement</key>
206+
<true/>
207+
<key>NSHumanReadableCopyright</key>
208+
<string>No Copyright</string>
209+
<key>NSMainNibFile</key>
210+
<string>MainMenu</string>
211+
<key>NSPrincipalClass</key>
212+
<string>NSApplication</string>
213+
</dict>
214+
</plist>
215+
EOF
216+
217+
test -e test.py && "${NAME}.app/Contents/Python/bin/python3.5" test.py
218+
219+
find "${NAME}.app" -d -name "__pycache__" -type d -exec rm -r "{}" \;
220+
find "${NAME}.app" -name "*.pyc" -exec rm "{}" \;

example/application/__init__.py

Whitespace-only changes.

example/application/__main__.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import tkinter as tk
2+
3+
class Application(tk.Frame):
4+
def __init__(self, master=None):
5+
super().__init__(master)
6+
self.pack()
7+
self.create_widgets()
8+
9+
def create_widgets(self):
10+
self.hi_there = tk.Button(self)
11+
self.hi_there["text"] = "Hello World\n(click me)"
12+
self.hi_there["command"] = self.say_hi
13+
self.hi_there.pack(side="top")
14+
15+
self.quit = tk.Button(self, text="QUIT", fg="red",
16+
command=root.destroy)
17+
self.quit.pack(side="bottom")
18+
19+
def say_hi(self):
20+
print("hi there, everyone!")
21+
22+
root = tk.Tk()
23+
app = Application(master=root)
24+
app.mainloop()
Binary file not shown.
Binary file not shown.

example/setup.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from distutils.core import setup
2+
3+
setup(name="application", packages=['application'])

requirements.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# add additional dependencies here
2+
lxml
3+
# i.e. add PyQt5
4+
#PyQt5
5+
6+
# main application
7+
# replace with your module that can be run via python3 -m application
8+
./example

test.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/usr/bin/env python3
2+
import ssl
3+
print('loaded ssl')
4+
import sqlite3
5+
print('loaded sqlite3')
6+
import lxml
7+
print('loaded lxml')
8+
9+
print('TEST OK')

0 commit comments

Comments
 (0)