Skip to content

Commit

Permalink
1.Add py2app support.
Browse files Browse the repository at this point in the history
2.Fix not responding problem.
  • Loading branch information
HsOjo committed Oct 20, 2019
1 parent 1863cc6 commit dc8ea96
Show file tree
Hide file tree
Showing 14 changed files with 201 additions and 92 deletions.
9 changes: 3 additions & 6 deletions __main__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import sys

from app import Application
from app.util import pyinstaller
from app.shell import init_app_shell
from app.util.log import Log

if getattr(sys, 'frozen', False):
# is run at pyinstaller
pyinstaller.fix_encoding_in_pyinstaller()
app_shell = init_app_shell()
if app_shell.check():
Log.init_app()

app = Application()
Expand Down
18 changes: 9 additions & 9 deletions app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
import rumps

from app import common
from .base.application import ApplicationBase
from .config import Config
from .res.const import Const
from .res.language import load_language, LANGUAGES
from .res.language.english import English
from .util import system_api, osa_api, github, object_convert, log
from .util.log import Log
from .util.process_daemon import ProcessDaemon
from .view.application import ApplicationView
from app.base.application import ApplicationBase
from app.config import Config
from app.res.const import Const
from app.res.language import load_language, LANGUAGES
from app.res.language.english import English
from app.util import system_api, osa_api, github, object_convert, log
from app.util.log import Log
from app.util.process_daemon import ProcessDaemon
from app.view.application import ApplicationView


class Application(ApplicationBase, ApplicationView):
Expand Down
16 changes: 12 additions & 4 deletions app/base/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,22 @@
from app.res.const import Const
from app.res.language import LANGUAGES, load_language
from app.res.language.english import English
from app.util import system_api, osa_api, pyinstaller, github, object_convert
from app.shell import get_app_shell
from app.util import system_api, osa_api, github, object_convert
from app.util.log import Log


class ApplicationBase:
def __init__(self, config_class):
Log.append('app_init', 'Info', 'version: %s' % Const.version, system_api.get_system_version())
self.app = rumps.App(Const.app_name, quit_button=None)
self.app_shell = get_app_shell()

Log.append('app_shell', 'Info', {
'shell_class': self.app_shell.__class__.__name__,
'runtime_dir': self.app_shell.get_runtime_dir(),
'app_path': self.app_shell.get_app_path(),
})

self.config = config_class()
self.config.load()
Expand Down Expand Up @@ -181,7 +189,7 @@ def message_box(self, title, description):

def run(self):
self.hook_exception()
self.app.icon = '%s/app/res/icon.png' % pyinstaller.get_runtime_dir()
self.app.icon = '%s/app/res/icon.png' % self.app_shell.get_runtime_dir()
self.app.run()

def hook_exception(self):
Expand All @@ -200,7 +208,7 @@ def quit(self):
rumps.quit_application()

def restart(self):
[_, path] = pyinstaller.get_application_info()
path = self.app_shell.get_app_path()
if path is not None:
system_api.open_url(path, True)
else:
Expand Down Expand Up @@ -309,7 +317,7 @@ def welcome(self):
def set_startup(self):
res = osa_api.alert(self.lang.menu_set_startup, self.lang.description_set_startup)
if res:
osa_api.set_login_startup(*pyinstaller.get_application_info())
osa_api.set_login_startup(Const.app_name, self.app_shell.get_app_path())

def clear_config(self, sender: rumps.MenuItem):
if osa_api.alert(sender.title, self.lang.description_clear_config):
Expand Down
2 changes: 1 addition & 1 deletion app/res/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ class Const:
author = 'HsOjo'
app_name = 'SleeperX'
app_env = '%s_ENV' % app_name.upper()
version = '1.6.9'
version = '1.7.0'
github_page = 'https://github.com/%s/%s' % (author, app_name)
releases_url = '%s/releases' % github_page
protector = '[protector]'
Expand Down
7 changes: 4 additions & 3 deletions app/res/language/translate_language.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import json
import os

from app.util import pyinstaller, object_convert
from app.util import object_convert
from app.util.log import Log
from tools.translate import Translator
from .english import English
Expand All @@ -15,8 +15,9 @@ class TranslateLanguage(English):
_replace_words = {}

def __init__(self):
self._data_path = '%s/app/res/language/translate/%s.json' % (
pyinstaller.get_runtime_dir(), self._resource_name[self._resource_name.rfind('.') + 1:])
self._data_path = './app/res/language/translate/%s.json' % (
self._resource_name[self._resource_name.rfind('.') + 1:]
)
self._translated = self.load_local_translate()

def load_local_translate(self):
Expand Down
21 changes: 21 additions & 0 deletions app/shell/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from .shell import Shell
from .py2app import Py2App
from .pyinstaller import PyInstaller

app_shell: Shell


def init_app_shell():
global app_shell
if PyInstaller.check():
app_shell = PyInstaller()
elif Py2App.check():
app_shell = Py2App()
else:
app_shell = Shell()

return app_shell


def get_app_shell():
return app_shell
16 changes: 16 additions & 0 deletions app/shell/py2app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import os

from .shell import Shell


class Py2App(Shell):
def __init__(self):
super().__init__()
if self.check():
self.fix_encoding()
self.runtime_dir = os.path.abspath(os.getcwd())
self.app_path = os.path.abspath('%s/../..' % self.runtime_dir)

@staticmethod
def check():
return os.getenv('_PY2APP_LAUNCHED_') is not None
18 changes: 18 additions & 0 deletions app/shell/pyinstaller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import os
import sys

from .shell import Shell


class PyInstaller(Shell):
def __init__(self):
super().__init__()
if self.check():
self.fix_encoding()
self.runtime_dir = os.path.abspath(getattr(sys, '_MEIPASS', '.'))
if getattr(sys, 'frozen', False):
self.app_path = os.path.abspath('%s/../../..' % sys.executable)

@staticmethod
def check():
return getattr(sys, '_MEIPASS', None) is not None
43 changes: 43 additions & 0 deletions app/shell/shell.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import sys
from subprocess import Popen


class Shell:
def __init__(self):
self.runtime_dir = '.'
self.app_path = None

@staticmethod
def check():
return False

def get_app_path(self):
return self.app_path

def get_runtime_dir(self):
return self.runtime_dir

@staticmethod
def fix_encoding():
encoding = sys.getdefaultencoding()
_init = Popen.__init__

def init(*args, **kwargs):
kwargs['encoding'] = kwargs.get('encoding', encoding)
return _init(*args, **kwargs)

Popen.__init__ = init

__open = open

def _open(*args, **kwargs):
if len(args) >= 2:
mode = args[1]
else:
mode = kwargs.get('mode')

if isinstance(mode, str) and 'b' not in mode:
kwargs['encoding'] = kwargs.get('encoding', encoding)
return __open(*args, **kwargs)

__builtins__['open'] = _open
42 changes: 0 additions & 42 deletions app/util/pyinstaller.py

This file was deleted.

56 changes: 34 additions & 22 deletions build.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,28 +41,40 @@ def add_data(src, dest):

add_data('./app/res/icon.png', './app/res')

data_str = ''
for k, v in datas.items():
data_str += ' \\\n\t'
data_str += '--add-data "%s:%s"' % (k, v)

Log.append('Build', 'Info', 'Pyinstaller packing now...')
pyi_cmd = 'pyinstaller -F -w -n "%s" -i "./app/res/icon.icns" %s \\\n__main__.py' % (Const.app_name, data_str)
print(pyi_cmd)
os.system(pyi_cmd)
os.unlink('./%s.spec' % Const.app_name)
shutil.rmtree('./build', ignore_errors=True)

# hide dock icon.
INFO_FILE = './dist/%s.app/Contents/Info.plist' % Const.app_name

with open(INFO_FILE, 'r') as io:
info = io.read()

dict_pos = info.find('<dict>') + 7
info = info[:dict_pos] + '\t<key>LSUIElement</key>\n\t<string>1</string>\n' + info[dict_pos:]
with open(INFO_FILE, 'w') as io:
io.write(info)
use_py2app = '--py2app' in sys.argv
if use_py2app:
Log.append('Build', 'Info', 'Py2App packing now...')
os.system('python setup.py py2app')
shutil.rmtree('./build', ignore_errors=True)

res_dir = './dist/%s.app/Contents/Resources' % Const.app_name
for f, fd in datas.items():
dd = ('%s/%s' % (res_dir, fd)).replace('/./', '/')
os.makedirs(dd, exist_ok=True)
shutil.copy(f, dd)
else:
data_str = ''
for k, v in datas.items():
data_str += ' \\\n\t'
data_str += '--add-data "%s:%s"' % (k, v)

Log.append('Build', 'Info', 'Pyinstaller packing now...')
pyi_cmd = 'pyinstaller -F -w -n "%s" -i "./app/res/icon.icns" %s \\\n__main__.py' % (Const.app_name, data_str)
print(pyi_cmd)
os.system(pyi_cmd)
os.unlink('./%s.spec' % Const.app_name)
shutil.rmtree('./build', ignore_errors=True)

# hide dock icon.
INFO_FILE = './dist/%s.app/Contents/Info.plist' % Const.app_name

with open(INFO_FILE, 'r') as io:
info = io.read()

dict_pos = info.find('<dict>') + 7
info = info[:dict_pos] + '\t<key>LSUIElement</key>\n\t<string>1</string>\n' + info[dict_pos:]
with open(INFO_FILE, 'w') as io:
io.write(info)

Log.append('Build', 'Info', 'Packing release zip file now...')

Expand Down
5 changes: 2 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
requests==2.22.0
rumps==0.3.0
opencv_python==4.1.0.25
PyExecJS==1.5.1
PyInstaller==3.5
PyInstaller==3.5
py2app==0.19
37 changes: 37 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""
This is a setup.py script generated by py2applet
Usage:
python setup.py py2app
"""

import time

from setuptools import setup

from app.res.const import Const

APP = ['__main__.py']
DATA_FILES = []
OPTIONS = {
'argv_emulation': True,
'iconfile': 'app/res/icon.icns',
'plist': {
'CFBundleName': Const.app_name,
'CFBundleDisplayName': Const.app_name,
'CFBundleGetInfoString': Const.github_page,
'CFBundleIdentifier': Const.app_name,
'CFBundleVersion': Const.version,
'CFBundleShortVersionString': Const.version,
'NSHumanReadableCopyright': "Copyright © %d, %s, All Rights Reserved" % (
time.localtime().tm_year, Const.author),
'LSUIElement': True,
}
}

setup(
app=APP,
data_files=DATA_FILES,
options={'py2app': OPTIONS},
setup_requires=['py2app', 'rumps', 'requests'],
)
3 changes: 1 addition & 2 deletions tools/translate/api/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import json
import os

from app.util import pyinstaller
from .baidu import BaiduTranslate
from .google import GoogleTranslate
from .translator import Translator
from .zhconv import ZHConv

CONFIG_FILE = '%s/tools/translate/config.json' % pyinstaller.get_runtime_dir()
CONFIG_FILE = './tools/translate/config.json'

config = {}
if os.path.exists(CONFIG_FILE):
Expand Down

0 comments on commit dc8ea96

Please sign in to comment.