mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Simplify launching of console utilities on macOS
This commit is contained in:
parent
b8968a82f8
commit
a7453e877a
@ -203,7 +203,6 @@ class Freeze(object):
|
|||||||
if not test_launchers and not self.dont_strip:
|
if not test_launchers and not self.dont_strip:
|
||||||
self.strip_files()
|
self.strip_files()
|
||||||
if not test_launchers:
|
if not test_launchers:
|
||||||
self.create_console_app()
|
|
||||||
self.create_gui_apps()
|
self.create_gui_apps()
|
||||||
|
|
||||||
self.run_tests()
|
self.run_tests()
|
||||||
@ -213,8 +212,7 @@ class Freeze(object):
|
|||||||
|
|
||||||
@flush
|
@flush
|
||||||
def run_tests(self):
|
def run_tests(self):
|
||||||
cc_dir = join(self.contents_dir, 'calibre-debug.app', 'Contents')
|
self.test_runner(join(self.contents_dir, 'MacOS', 'calibre-debug'), self.contents_dir)
|
||||||
self.test_runner(join(cc_dir, 'MacOS', 'calibre-debug'), self.contents_dir)
|
|
||||||
|
|
||||||
@flush
|
@flush
|
||||||
def add_resources(self):
|
def add_resources(self):
|
||||||
@ -677,14 +675,6 @@ class Freeze(object):
|
|||||||
else:
|
else:
|
||||||
os.symlink(join('../..', x), join(cc_dir, x))
|
os.symlink(join('../..', x), join(cc_dir, x))
|
||||||
|
|
||||||
@flush
|
|
||||||
def create_console_app(self):
|
|
||||||
def specialise_plist(plist):
|
|
||||||
plist['LSBackgroundOnly'] = '1'
|
|
||||||
plist['CFBundleIdentifier'] = 'com.calibre-ebook.console'
|
|
||||||
plist['CFBundleExecutable'] = 'calibre-parallel'
|
|
||||||
self.create_app_clone('console.app', specialise_plist)
|
|
||||||
|
|
||||||
@flush
|
@flush
|
||||||
def create_gui_apps(self):
|
def create_gui_apps(self):
|
||||||
input_formats = sorted(set(json.loads(
|
input_formats = sorted(set(json.loads(
|
||||||
@ -696,19 +686,17 @@ class Freeze(object):
|
|||||||
|
|
||||||
def specialise_plist(launcher, remove_types, plist):
|
def specialise_plist(launcher, remove_types, plist):
|
||||||
plist['CFBundleDisplayName'] = plist['CFBundleName'] = {
|
plist['CFBundleDisplayName'] = plist['CFBundleName'] = {
|
||||||
'ebook-viewer': 'E-book Viewer', 'ebook-edit': 'Edit Book', 'calibre-debug': 'calibre (debug)',
|
'ebook-viewer': 'E-book Viewer', 'ebook-edit': 'Edit Book',
|
||||||
}[launcher]
|
}[launcher]
|
||||||
plist['CFBundleExecutable'] = launcher
|
plist['CFBundleExecutable'] = launcher
|
||||||
if launcher != 'calibre-debug':
|
|
||||||
plist['CFBundleIconFile'] = launcher + '.icns'
|
|
||||||
plist['CFBundleIdentifier'] = 'com.calibre-ebook.' + launcher
|
plist['CFBundleIdentifier'] = 'com.calibre-ebook.' + launcher
|
||||||
|
plist['CFBundleIconFile'] = launcher + '.icns'
|
||||||
if not remove_types:
|
if not remove_types:
|
||||||
e = plist['CFBundleDocumentTypes'][0]
|
e = plist['CFBundleDocumentTypes'][0]
|
||||||
exts = 'epub azw3'.split() if launcher == 'ebook-edit' else input_formats
|
exts = 'epub azw3'.split() if launcher == 'ebook-edit' else input_formats
|
||||||
e['CFBundleTypeExtensions'] = exts
|
e['CFBundleTypeExtensions'] = exts
|
||||||
for launcher in ('ebook-viewer', 'ebook-edit', 'calibre-debug'):
|
for launcher in ('ebook-viewer', 'ebook-edit'):
|
||||||
remove_types = launcher == 'calibre-debug'
|
self.create_app_clone(launcher + '.app', partial(specialise_plist, launcher, False), remove_doc_types=False)
|
||||||
self.create_app_clone(launcher + '.app', partial(specialise_plist, launcher, remove_types), remove_doc_types=remove_types)
|
|
||||||
|
|
||||||
@flush
|
@flush
|
||||||
def copy_site(self):
|
def copy_site(self):
|
||||||
|
@ -7,10 +7,12 @@ This is stripped down and customized for use in py2app applications
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
def makepath(*paths):
|
def makepath(*paths):
|
||||||
dir = os.path.abspath(os.path.join(*paths))
|
dir = os.path.abspath(os.path.join(*paths))
|
||||||
return dir, os.path.normcase(dir)
|
return dir, os.path.normcase(dir)
|
||||||
|
|
||||||
|
|
||||||
def abs__file__():
|
def abs__file__():
|
||||||
"""Set all module __file__ attribute to an absolute path"""
|
"""Set all module __file__ attribute to an absolute path"""
|
||||||
for m in sys.modules.values():
|
for m in sys.modules.values():
|
||||||
@ -21,6 +23,7 @@ def abs__file__():
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
||||||
# This ensures that the initial path provided by the interpreter contains
|
# This ensures that the initial path provided by the interpreter contains
|
||||||
# only absolute pathnames, even if we're running from the build directory.
|
# only absolute pathnames, even if we're running from the build directory.
|
||||||
L = []
|
L = []
|
||||||
@ -38,6 +41,7 @@ sys.path[:] = L
|
|||||||
del dir, dircase, L
|
del dir, dircase, L
|
||||||
_dirs_in_sys_path = None
|
_dirs_in_sys_path = None
|
||||||
|
|
||||||
|
|
||||||
def _init_pathinfo():
|
def _init_pathinfo():
|
||||||
global _dirs_in_sys_path
|
global _dirs_in_sys_path
|
||||||
_dirs_in_sys_path = d = {}
|
_dirs_in_sys_path = d = {}
|
||||||
@ -47,6 +51,7 @@ def _init_pathinfo():
|
|||||||
dir, dircase = makepath(dir)
|
dir, dircase = makepath(dir)
|
||||||
d[dircase] = 1
|
d[dircase] = 1
|
||||||
|
|
||||||
|
|
||||||
def addsitedir(sitedir):
|
def addsitedir(sitedir):
|
||||||
global _dirs_in_sys_path
|
global _dirs_in_sys_path
|
||||||
if _dirs_in_sys_path is None:
|
if _dirs_in_sys_path is None:
|
||||||
@ -68,6 +73,7 @@ def addsitedir(sitedir):
|
|||||||
if reset:
|
if reset:
|
||||||
_dirs_in_sys_path = None
|
_dirs_in_sys_path = None
|
||||||
|
|
||||||
|
|
||||||
def addpackage(sitedir, name):
|
def addpackage(sitedir, name):
|
||||||
global _dirs_in_sys_path
|
global _dirs_in_sys_path
|
||||||
if _dirs_in_sys_path is None:
|
if _dirs_in_sys_path is None:
|
||||||
@ -107,29 +113,31 @@ if hasattr(sys, "setdefaultencoding"):
|
|||||||
sys.setdefaultencoding('utf-8')
|
sys.setdefaultencoding('utf-8')
|
||||||
del sys.setdefaultencoding
|
del sys.setdefaultencoding
|
||||||
|
|
||||||
|
|
||||||
def run_entry_point():
|
def run_entry_point():
|
||||||
bname, mod, func = sys.calibre_basename, sys.calibre_module, sys.calibre_function
|
bname, mod, func = sys.calibre_basename, sys.calibre_module, sys.calibre_function
|
||||||
sys.argv[0] = bname
|
sys.argv[0] = bname
|
||||||
pmod = __import__(mod, fromlist=[1], level=0)
|
pmod = __import__(mod, fromlist=[1], level=0)
|
||||||
return getattr(pmod, func)()
|
return getattr(pmod, func)()
|
||||||
|
|
||||||
|
|
||||||
def add_calibre_vars(base):
|
def add_calibre_vars(base):
|
||||||
sys.frameworks_dir = os.path.join(os.path.dirname(base), 'Frameworks')
|
sys.frameworks_dir = os.path.join(os.path.dirname(base), 'Frameworks')
|
||||||
sys.resources_location = os.path.abspath(os.path.join(base, 'resources'))
|
sys.resources_location = os.path.abspath(os.path.join(base, 'resources'))
|
||||||
sys.extensions_location = os.path.join(sys.frameworks_dir, 'plugins')
|
sys.extensions_location = os.path.join(sys.frameworks_dir, 'plugins')
|
||||||
sys.binaries_path = os.path.join(os.path.dirname(base), 'MacOS')
|
sys.binaries_path = os.path.join(os.path.dirname(base), 'MacOS')
|
||||||
sys.console_binaries_path = os.path.join(os.path.dirname(base),
|
|
||||||
'console.app', 'Contents', 'MacOS')
|
|
||||||
|
|
||||||
dv = os.environ.get('CALIBRE_DEVELOP_FROM', None)
|
dv = os.environ.get('CALIBRE_DEVELOP_FROM', None)
|
||||||
if dv and os.path.exists(dv):
|
if dv and os.path.exists(dv):
|
||||||
sys.path.insert(0, os.path.abspath(dv))
|
sys.path.insert(0, os.path.abspath(dv))
|
||||||
|
|
||||||
|
|
||||||
def nuke_stdout():
|
def nuke_stdout():
|
||||||
# Redirect stdout, stdin and stderr to /dev/null
|
# Redirect stdout, stdin and stderr to /dev/null
|
||||||
from calibre.constants import plugins
|
from calibre.constants import plugins
|
||||||
plugins['speedup'][0].detach(os.devnull)
|
plugins['speedup'][0].detach(os.devnull)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
global __file__
|
global __file__
|
||||||
|
|
||||||
@ -148,7 +156,8 @@ def main():
|
|||||||
addsitedir(sys.site_packages)
|
addsitedir(sys.site_packages)
|
||||||
|
|
||||||
if sys.calibre_is_gui_app and not (
|
if sys.calibre_is_gui_app and not (
|
||||||
sys.stdout.isatty() or sys.stderr.isatty() or sys.stdin.isatty()):
|
sys.stdout.isatty() or sys.stderr.isatty() or sys.stdin.isatty()
|
||||||
|
):
|
||||||
nuke_stdout()
|
nuke_stdout()
|
||||||
|
|
||||||
return run_entry_point()
|
return run_entry_point()
|
||||||
|
@ -37,7 +37,7 @@ the directory in which you created :file:`__init__.py`::
|
|||||||
.. note::
|
.. note::
|
||||||
On macOS, the command line tools are inside the calibre bundle, for example,
|
On macOS, the command line tools are inside the calibre bundle, for example,
|
||||||
if you installed calibre in :file:`/Applications` the command line tools
|
if you installed calibre in :file:`/Applications` the command line tools
|
||||||
are in :file:`/Applications/calibre.app/Contents/console.app/Contents/MacOS/`.
|
are in :file:`/Applications/calibre.app/Contents/MacOS/`.
|
||||||
|
|
||||||
You can download the Hello World plugin from
|
You can download the Hello World plugin from
|
||||||
`helloworld_plugin.zip <https://calibre-ebook.com/downloads/helloworld_plugin.zip>`_.
|
`helloworld_plugin.zip <https://calibre-ebook.com/downloads/helloworld_plugin.zip>`_.
|
||||||
@ -325,4 +325,3 @@ Sharing your plugins with others
|
|||||||
|
|
||||||
If you would like to share the plugins you have created with other users of calibre, post your plugin in a new thread in the
|
If you would like to share the plugins you have created with other users of calibre, post your plugin in a new thread in the
|
||||||
`calibre plugins forum <https://www.mobileread.com/forums/forumdisplay.php?f=237>`_.
|
`calibre plugins forum <https://www.mobileread.com/forums/forumdisplay.php?f=237>`_.
|
||||||
|
|
||||||
|
@ -198,7 +198,7 @@ the previously checked out calibre code directory, for example::
|
|||||||
|
|
||||||
calibre is the directory that contains the src and resources sub-directories.
|
calibre is the directory that contains the src and resources sub-directories.
|
||||||
The calibre command line tools are found inside the calibre app bundle, in
|
The calibre command line tools are found inside the calibre app bundle, in
|
||||||
:file:`/Applications/calibre.app/Contents/console.app/Contents/MacOS`
|
:file:`/Applications/calibre.app/Contents/MacOS`
|
||||||
you should add this directory to your PATH environment variable, if you want to
|
you should add this directory to your PATH environment variable, if you want to
|
||||||
run the command line tools easily.
|
run the command line tools easily.
|
||||||
|
|
||||||
|
@ -311,7 +311,7 @@ If you're satisfied with your recipe, and you feel there is enough demand to jus
|
|||||||
.. note::
|
.. note::
|
||||||
On macOS, the command line tools are inside the calibre bundle, for example,
|
On macOS, the command line tools are inside the calibre bundle, for example,
|
||||||
if you installed calibre in :file:`/Applications` the command line tools
|
if you installed calibre in :file:`/Applications` the command line tools
|
||||||
are in :file:`/Applications/calibre.app/Contents/console.app/Contents/MacOS/`.
|
are in :file:`/Applications/calibre.app/Contents/MacOS/`.
|
||||||
|
|
||||||
.. seealso::
|
.. seealso::
|
||||||
|
|
||||||
|
@ -17,8 +17,6 @@ from polyglot.builtins import exec_path, raw_input, unicode_type, getcwd
|
|||||||
def get_debug_executable():
|
def get_debug_executable():
|
||||||
if hasattr(sys, 'frameworks_dir'):
|
if hasattr(sys, 'frameworks_dir'):
|
||||||
base = os.path.dirname(sys.frameworks_dir)
|
base = os.path.dirname(sys.frameworks_dir)
|
||||||
if 'calibre-debug.app' not in base:
|
|
||||||
base = os.path.join(base, 'calibre-debug.app', 'Contents')
|
|
||||||
return os.path.join(base, 'MacOS', 'calibre-debug')
|
return os.path.join(base, 'MacOS', 'calibre-debug')
|
||||||
if getattr(sys, 'frozen', False):
|
if getattr(sys, 'frozen', False):
|
||||||
return os.path.join(os.path.dirname(os.path.abspath(sys.executable)), 'calibre-debug' + ('.exe' if iswindows else ''))
|
return os.path.join(os.path.dirname(os.path.abspath(sys.executable)), 'calibre-debug' + ('.exe' if iswindows else ''))
|
||||||
|
@ -1201,6 +1201,8 @@ def ensure_app(headless=True):
|
|||||||
has_headless = isosx or islinux or isbsd
|
has_headless = isosx or islinux or isbsd
|
||||||
if headless and has_headless:
|
if headless and has_headless:
|
||||||
args += ['-platformpluginpath', plugins_loc, '-platform', 'headless']
|
args += ['-platformpluginpath', plugins_loc, '-platform', 'headless']
|
||||||
|
if isosx:
|
||||||
|
os.environ['QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM'] = '1'
|
||||||
_store_app = QApplication(args)
|
_store_app = QApplication(args)
|
||||||
if headless and has_headless:
|
if headless and has_headless:
|
||||||
_store_app.headless = True
|
_store_app.headless = True
|
||||||
|
@ -1183,7 +1183,7 @@ def cli_index_strings():
|
|||||||
return _('Command Line Interface'), _(
|
return _('Command Line Interface'), _(
|
||||||
'On macOS, the command line tools are inside the calibre bundle, for example,'
|
'On macOS, the command line tools are inside the calibre bundle, for example,'
|
||||||
' if you installed calibre in :file:`/Applications` the command line tools'
|
' if you installed calibre in :file:`/Applications` the command line tools'
|
||||||
' are in :file:`/Applications/calibre.app/Contents/console.app/Contents/MacOS/`.'), _(
|
' are in :file:`/Applications/calibre.app/Contents/MacOS/`.'), _(
|
||||||
'Documented commands'), _('Undocumented commands'), _(
|
'Documented commands'), _('Undocumented commands'), _(
|
||||||
'You can see usage for undocumented commands by executing them without arguments in a terminal.'), _(
|
'You can see usage for undocumented commands by executing them without arguments in a terminal.'), _(
|
||||||
'Change language'), _('Search')
|
'Change language'), _('Search')
|
||||||
|
@ -59,7 +59,7 @@ class Worker(object):
|
|||||||
return os.path.join(os.path.dirname(sys.executable),
|
return os.path.join(os.path.dirname(sys.executable),
|
||||||
e+'.exe' if isfrozen else 'Scripts\\%s.exe'%e)
|
e+'.exe' if isfrozen else 'Scripts\\%s.exe'%e)
|
||||||
if isosx:
|
if isosx:
|
||||||
return os.path.join(sys.console_binaries_path, e)
|
return os.path.join(sys.binaries_path, e)
|
||||||
|
|
||||||
if isfrozen:
|
if isfrozen:
|
||||||
return os.path.join(sys.executables_location, e)
|
return os.path.join(sys.executables_location, e)
|
||||||
@ -74,7 +74,7 @@ class Worker(object):
|
|||||||
def gui_executable(self):
|
def gui_executable(self):
|
||||||
if isosx and not hasattr(sys, 'running_from_setup'):
|
if isosx and not hasattr(sys, 'running_from_setup'):
|
||||||
if self.job_name in {'ebook-viewer', 'ebook-edit'}:
|
if self.job_name in {'ebook-viewer', 'ebook-edit'}:
|
||||||
return self.executable.replace('/console.app/', '/%s.app/' % self.job_name)
|
return self.executable.replace('/Contents/', '/Contents/%s.app/Contents/' % self.job_name)
|
||||||
return os.path.join(sys.binaries_path, self.exe_name)
|
return os.path.join(sys.binaries_path, self.exe_name)
|
||||||
|
|
||||||
return self.executable
|
return self.executable
|
||||||
|
Loading…
x
Reference in New Issue
Block a user