py2app fixes
This commit is contained in:
Executable → Regular
+153
-49
@@ -1,63 +1,167 @@
|
|||||||
#!/usr/bin/env python
|
from threading import Thread
|
||||||
# -*- coding: utf-8 -*-
|
from wx.lib.softwareupdate import SoftwareUpdate
|
||||||
'''Wrapper for the command line interface.'''
|
|
||||||
|
|
||||||
from os.path import dirname
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import subprocess
|
import webbrowser
|
||||||
import time
|
import wx
|
||||||
|
|
||||||
|
|
||||||
# Root path
|
# Include proper dirs
|
||||||
base_path = dirname(os.path.abspath(__file__))
|
if hasattr(sys, 'frozen'):
|
||||||
|
import libs
|
||||||
|
base_path = os.path.dirname(os.path.dirname(os.path.abspath(libs.__file__)))
|
||||||
|
print base_path
|
||||||
|
else:
|
||||||
|
base_path = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
# Insert local directories into path
|
lib_dir = os.path.join(base_path, 'libs')
|
||||||
sys.path.insert(0, os.path.join(base_path, 'libs'))
|
|
||||||
|
|
||||||
from couchpotato.core.logger import CPLog
|
sys.path.insert(0, base_path)
|
||||||
log = CPLog(__name__)
|
sys.path.insert(0, lib_dir)
|
||||||
|
|
||||||
# Get options via arg
|
# Get options via arg
|
||||||
from couchpotato.runner import getOptions
|
from couchpotato.runner import getOptions
|
||||||
from couchpotato.core.helpers.variable import getDataDir
|
|
||||||
options = getOptions(base_path, sys.argv[1:])
|
|
||||||
data_dir = getDataDir()
|
|
||||||
|
|
||||||
def start():
|
|
||||||
try:
|
|
||||||
args = [sys.executable] + sys.argv
|
|
||||||
new_environ = os.environ.copy()
|
|
||||||
new_environ['cp_main'] = 'true'
|
|
||||||
|
|
||||||
if os.name == 'nt':
|
|
||||||
for key, value in new_environ.iteritems():
|
|
||||||
if isinstance(value, unicode):
|
|
||||||
new_environ[key] = value.encode('iso-8859-1')
|
|
||||||
|
|
||||||
subprocess.call(args, env = new_environ)
|
|
||||||
return os.path.isfile(os.path.join(data_dir, 'restart'))
|
|
||||||
except KeyboardInterrupt, e:
|
|
||||||
pass
|
|
||||||
except Exception, e:
|
|
||||||
log.critical(e)
|
|
||||||
return 0
|
|
||||||
|
|
||||||
from couchpotato.runner import runCouchPotato
|
from couchpotato.runner import runCouchPotato
|
||||||
if __name__ == '__main__':
|
|
||||||
|
|
||||||
if os.environ.get('cp_main', 'false') == 'true':
|
|
||||||
|
class TaskBarIcon(wx.TaskBarIcon):
|
||||||
|
|
||||||
|
TBMENU_OPEN = wx.NewId()
|
||||||
|
TBMENU_SETTINGS = wx.NewId()
|
||||||
|
TBMENU_ABOUT = wx.ID_ABOUT
|
||||||
|
TBMENU_EXIT = wx.ID_EXIT
|
||||||
|
|
||||||
|
def __init__(self, frame):
|
||||||
|
wx.TaskBarIcon.__init__(self)
|
||||||
|
self.frame = frame
|
||||||
|
|
||||||
|
icon = wx.Icon('icon.ico', wx.BITMAP_TYPE_ANY)
|
||||||
|
self.SetIcon(icon)
|
||||||
|
|
||||||
|
self.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.onTaskBarActivate)
|
||||||
|
|
||||||
|
self.Bind(wx.EVT_MENU, self.onOpen, id = self.TBMENU_OPEN)
|
||||||
|
self.Bind(wx.EVT_MENU, self.onSettings, id = self.TBMENU_SETTINGS)
|
||||||
|
self.Bind(wx.EVT_MENU, self.onAbout, id = self.TBMENU_ABOUT)
|
||||||
|
self.Bind(wx.EVT_MENU, self.onTaskBarClose, id = self.TBMENU_EXIT)
|
||||||
|
|
||||||
|
|
||||||
|
def CreatePopupMenu(self):
|
||||||
|
menu = wx.Menu()
|
||||||
|
menu.Append(self.TBMENU_OPEN, "Open")
|
||||||
|
menu.Append(self.TBMENU_SETTINGS, "Settings")
|
||||||
|
menu.Append(self.TBMENU_ABOUT, "About")
|
||||||
|
menu.Append(self.TBMENU_EXIT, "Close")
|
||||||
|
return menu
|
||||||
|
|
||||||
|
def onOpen(self, event):
|
||||||
|
url = self.frame.parent.getSetting('base_url')
|
||||||
|
webbrowser.open(url)
|
||||||
|
|
||||||
|
def onSettings(self, event):
|
||||||
|
url = self.frame.parent.getSetting('base_url') + '/settings/'
|
||||||
|
webbrowser.open(url)
|
||||||
|
|
||||||
|
def onAbout(self, event):
|
||||||
|
print 'onAbout'
|
||||||
|
|
||||||
|
def onTaskBarActivate(self, evt):
|
||||||
|
if not self.frame.IsShown():
|
||||||
|
self.frame.Show(True)
|
||||||
|
self.frame.Raise()
|
||||||
|
|
||||||
|
def onTaskBarClose(self, evt):
|
||||||
|
wx.CallAfter(self.frame.Close)
|
||||||
|
|
||||||
|
def makeIcon(self, img):
|
||||||
|
if "wxMSW" in wx.PlatformInfo:
|
||||||
|
img = img.Scale(16, 16)
|
||||||
|
elif "wxGTK" in wx.PlatformInfo:
|
||||||
|
img = img.Scale(22, 22)
|
||||||
|
|
||||||
|
icon = wx.IconFromBitmap(img.CopyFromBitmap())
|
||||||
|
return icon
|
||||||
|
|
||||||
|
|
||||||
|
class MainFrame(wx.Frame):
|
||||||
|
|
||||||
|
def __init__(self, parent):
|
||||||
|
wx.Frame.__init__(self, None)
|
||||||
|
|
||||||
|
self.parent = parent
|
||||||
|
self.tbicon = TaskBarIcon(self)
|
||||||
|
|
||||||
|
|
||||||
|
class WorkerThread(Thread):
|
||||||
|
|
||||||
|
def __init__(self, desktop):
|
||||||
|
Thread.__init__(self)
|
||||||
|
self._desktop = desktop
|
||||||
|
|
||||||
|
self.start()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
|
||||||
|
args = ['--nogit', '--console_log']#, '--quiet']
|
||||||
|
options = getOptions(base_path, args)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
runCouchPotato(options, base_path, sys.argv[1:])
|
runCouchPotato(options, base_path, args, desktop = self._desktop)
|
||||||
|
except KeyboardInterrupt, e:
|
||||||
|
raise
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
log.critical(e)
|
raise
|
||||||
else:
|
finally:
|
||||||
while 1:
|
pass
|
||||||
restart = start()
|
|
||||||
if not restart:
|
|
||||||
break
|
|
||||||
|
|
||||||
from couchpotato.core.event import fireEvent
|
|
||||||
fireEvent('app.crappy_shutdown', single = True)
|
class CouchPotatoApp(wx.App, SoftwareUpdate):
|
||||||
time.sleep(1)
|
|
||||||
sys.exit()
|
settings = {}
|
||||||
|
events = {}
|
||||||
|
restart = False
|
||||||
|
|
||||||
|
def OnInit(self):
|
||||||
|
|
||||||
|
# Updater
|
||||||
|
base_url = 'http://couchpotatoapp.com/updates/'
|
||||||
|
self.InitUpdates(base_url, base_url + 'changelog.txt',
|
||||||
|
icon = wx.Icon('icon.ico'))
|
||||||
|
|
||||||
|
self.frame = MainFrame(self)
|
||||||
|
self.frame.Bind(wx.EVT_CLOSE, self.onClose)
|
||||||
|
|
||||||
|
# CouchPotato thread
|
||||||
|
self.worker = WorkerThread(self)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def setSettings(self, settings = {}):
|
||||||
|
self.settings = settings
|
||||||
|
|
||||||
|
def getSetting(self, name):
|
||||||
|
return self.settings.get(name)
|
||||||
|
|
||||||
|
def addEvents(self, events = {}):
|
||||||
|
for name in events.iterkeys():
|
||||||
|
self.events[name] = events[name]
|
||||||
|
|
||||||
|
def onClose(self, event):
|
||||||
|
onClose = self.events.get('onClose')
|
||||||
|
if self.events.get('onClose'):
|
||||||
|
onClose(event)
|
||||||
|
else:
|
||||||
|
self.afterShutdown()
|
||||||
|
|
||||||
|
def afterShutdown(self, restart = False):
|
||||||
|
self.frame.Destroy()
|
||||||
|
self.restart = restart
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app = CouchPotatoApp(redirect = False)
|
||||||
|
app.MainLoop()
|
||||||
|
|
||||||
|
#path = os.path.join(sys.path[0].decode(sys.getfilesystemencoding()), sys.argv[0])
|
||||||
|
#if app.restart:
|
||||||
|
# wx.Process.Open(sys.executable + ' ' + path)
|
||||||
|
|||||||
@@ -1,5 +1 @@
|
|||||||
CouchPotato Server
|
CouchPotato Desktop
|
||||||
=====
|
|
||||||
|
|
||||||
CouchPotato (CP) is an automatic NZB and torrent downloader. You can keep a "movies I want"-list and it will search for NZBs/torrents of these movies every X hours.
|
|
||||||
Once a movie is found, it will send it to SABnzbd or download the torrent to a specified directory.
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
from couchpotato import app
|
|
||||||
from couchpotato.api import addApiView
|
from couchpotato.api import addApiView
|
||||||
from couchpotato.core.event import fireEvent, addEvent
|
from couchpotato.core.event import fireEvent, addEvent
|
||||||
from couchpotato.core.helpers.request import jsonified
|
from couchpotato.core.helpers.request import jsonified
|
||||||
@@ -7,7 +6,6 @@ from couchpotato.core.logger import CPLog
|
|||||||
from couchpotato.core.plugins.base import Plugin
|
from couchpotato.core.plugins.base import Plugin
|
||||||
from couchpotato.environment import Env
|
from couchpotato.environment import Env
|
||||||
from flask import request
|
from flask import request
|
||||||
from flask.helpers import url_for
|
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
@@ -29,6 +27,7 @@ class Core(Plugin):
|
|||||||
addEvent('app.crappy_restart', self.crappyRestart)
|
addEvent('app.crappy_restart', self.crappyRestart)
|
||||||
addEvent('app.load', self.launchBrowser, priority = 1)
|
addEvent('app.load', self.launchBrowser, priority = 1)
|
||||||
addEvent('app.base_url', self.createBaseUrl)
|
addEvent('app.base_url', self.createBaseUrl)
|
||||||
|
addEvent('app.api_url', self.createApiUrl)
|
||||||
|
|
||||||
addEvent('setting.save.core.password', self.md5Password)
|
addEvent('setting.save.core.password', self.md5Password)
|
||||||
|
|
||||||
@@ -43,16 +42,10 @@ class Core(Plugin):
|
|||||||
})
|
})
|
||||||
|
|
||||||
def crappyShutdown(self):
|
def crappyShutdown(self):
|
||||||
ctx = app.test_request_context()
|
self.urlopen('%sapp.shutdown' % self.createApiUrl())
|
||||||
ctx.push()
|
|
||||||
self.urlopen('%s%sapp.shutdown' % (fireEvent('app.base_url', single = True), url_for('api.index')))
|
|
||||||
ctx.pop()
|
|
||||||
|
|
||||||
def crappyRestart(self):
|
def crappyRestart(self):
|
||||||
ctx = app.test_request_context()
|
self.urlopen('%sapp.restart' % self.createApiUrl())
|
||||||
ctx.push()
|
|
||||||
self.urlopen('%s%sapp.restart' % (fireEvent('app.base_url', single = True), url_for('api.index')))
|
|
||||||
ctx.pop()
|
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
self.initShutdown()
|
self.initShutdown()
|
||||||
@@ -63,6 +56,7 @@ class Core(Plugin):
|
|||||||
return 'restarting'
|
return 'restarting'
|
||||||
|
|
||||||
def initShutdown(self, restart = False):
|
def initShutdown(self, restart = False):
|
||||||
|
log.info('Shutting down' if not restart else 'Restarting')
|
||||||
|
|
||||||
fireEvent('app.shutdown')
|
fireEvent('app.shutdown')
|
||||||
|
|
||||||
@@ -122,3 +116,7 @@ class Core(Plugin):
|
|||||||
port = Env.setting('port')
|
port = Env.setting('port')
|
||||||
|
|
||||||
return '%s:%d' % (cleanHost(host).rstrip('/'), int(port))
|
return '%s:%d' % (cleanHost(host).rstrip('/'), int(port))
|
||||||
|
|
||||||
|
def createApiUrl(self):
|
||||||
|
|
||||||
|
return '%s/%s/' % (self.createBaseUrl(), Env.setting('api_key'))
|
||||||
|
|||||||
@@ -7,25 +7,28 @@ log = CPLog(__name__)
|
|||||||
|
|
||||||
if Env.get('desktop'):
|
if Env.get('desktop'):
|
||||||
|
|
||||||
#import os
|
|
||||||
#import sys
|
|
||||||
import wx
|
|
||||||
|
|
||||||
class Desktop(Plugin):
|
class Desktop(Plugin):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
desktop = Env.get('desktop')
|
desktop = Env.get('desktop')
|
||||||
desktop.setSettings({
|
desktop.setSettings({
|
||||||
'url': fireEvent('app.base_url', single = True)
|
'base_url': fireEvent('app.base_url', single = True),
|
||||||
|
'api_url': fireEvent('app.api_url', single = True),
|
||||||
|
'api': Env.setting('api'),
|
||||||
})
|
})
|
||||||
|
|
||||||
def onClose(event):
|
# Events from desktop
|
||||||
return fireEvent('app.crappy_shutdown')
|
desktop.addEvents({
|
||||||
desktop.close_handler = onClose
|
'onClose': self.onClose,
|
||||||
|
})
|
||||||
|
|
||||||
|
# Events to desktop
|
||||||
addEvent('app.after_shutdown', desktop.afterShutdown)
|
addEvent('app.after_shutdown', desktop.afterShutdown)
|
||||||
|
|
||||||
|
def onClose(self, event):
|
||||||
|
return fireEvent('app.crappy_shutdown', single = True)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
class Desktop(Plugin):
|
class Desktop(Plugin):
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class Env(object):
|
|||||||
_args = None
|
_args = None
|
||||||
_quiet = False
|
_quiet = False
|
||||||
_deamonize = False
|
_deamonize = False
|
||||||
_version = 0.5
|
_desktop = None
|
||||||
|
|
||||||
''' Data paths and directories '''
|
''' Data paths and directories '''
|
||||||
_app_dir = ""
|
_app_dir = ""
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
import ntpath
|
|
||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
|
|
||||||
@@ -45,7 +44,7 @@ def split_path(path):
|
|||||||
"""
|
"""
|
||||||
result = []
|
result = []
|
||||||
while True:
|
while True:
|
||||||
head, tail = ntpath.split(path)
|
head, tail = os.path.split(path)
|
||||||
|
|
||||||
# on Unix systems, the root folder is '/'
|
# on Unix systems, the root folder is '/'
|
||||||
if head == '/' and tail == '':
|
if head == '/' and tail == '':
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
from esky import bdist_esky
|
||||||
|
from setuptools import setup
|
||||||
|
import sys
|
||||||
|
import version
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
# Include proper dirs
|
||||||
|
base_path = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
lib_dir = os.path.join(base_path, 'libs')
|
||||||
|
|
||||||
|
sys.path.insert(0, base_path)
|
||||||
|
sys.path.insert(0, lib_dir)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Windows
|
||||||
|
if sys.platform == "win32":
|
||||||
|
import py2exe
|
||||||
|
|
||||||
|
FREEZER = 'py2exe'
|
||||||
|
FREEZER_OPTIONS = dict(
|
||||||
|
compressed = 0,
|
||||||
|
optimize = 0,
|
||||||
|
bundle_files = 3,
|
||||||
|
dll_excludes = [
|
||||||
|
'MSVCP90.dll',
|
||||||
|
'mswsock.dll',
|
||||||
|
'powrprof.dll',
|
||||||
|
'USP10.dll',
|
||||||
|
],
|
||||||
|
packages = ['couchpotato', 'libs'],
|
||||||
|
includes = [
|
||||||
|
'telnetlib',
|
||||||
|
'xml.etree.ElementTree',
|
||||||
|
'xml.etree.cElementTree',
|
||||||
|
'xml.dom',
|
||||||
|
'xml.dom.minidom',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
exeICON = 'icon.ico'
|
||||||
|
|
||||||
|
|
||||||
|
# OSX
|
||||||
|
elif sys.platform == "darwin":
|
||||||
|
import py2app
|
||||||
|
|
||||||
|
FREEZER = 'py2app'
|
||||||
|
FREEZER_OPTIONS = dict(
|
||||||
|
argv_emulation = False,
|
||||||
|
iconfile = 'icon.icns',
|
||||||
|
plist = dict(
|
||||||
|
LSUIElement = True,
|
||||||
|
),
|
||||||
|
packages = ['couchpotato', 'libs'],
|
||||||
|
includes = [
|
||||||
|
'telnetlib',
|
||||||
|
'xml.etree.ElementTree',
|
||||||
|
'xml.etree.cElementTree',
|
||||||
|
'xml.dom',
|
||||||
|
'xml.dom.minidom',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
exeICON = None
|
||||||
|
|
||||||
|
# Common
|
||||||
|
NAME = "CouchPotato"
|
||||||
|
APP = [bdist_esky.Executable("CouchPotato.py", gui_only = True, icon = exeICON,)]
|
||||||
|
DATA_FILES = ['icon.ico']
|
||||||
|
ESKY_OPTIONS = dict(
|
||||||
|
freezer_module = FREEZER,
|
||||||
|
freezer_options = FREEZER_OPTIONS,
|
||||||
|
bundle_msvcrt = True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Build the app and the esky bundle
|
||||||
|
setup(
|
||||||
|
name = NAME,
|
||||||
|
scripts = APP,
|
||||||
|
version = version.VERSION,
|
||||||
|
data_files = DATA_FILES,
|
||||||
|
options = dict(bdist_esky = ESKY_OPTIONS),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
VERSION = '0.5'
|
||||||
Reference in New Issue
Block a user