def _find_mupdf(): _mupdf['found'] = False _mupdf['version'] = None _mupdf['mutool'] = [] _mupdf['mudraw'] = [] _mupdf['mudraw_trace_args'] = [] if (mutool := process.find_executable(('mutool', ))) is None: return log.debug('mutool executable not found')
def is_available(): global _pdf_possible if _pdf_possible is not None: return _pdf_possible global _mutool_exec, _mudraw_exec, _mudraw_trace_args mutool = process.find_executable((u'mutool', )) _pdf_possible = False version = None if mutool is None: log.debug('mutool executable not found') else: _mutool_exec = [mutool] # Find MuPDF version; assume 1.6 version since # the '-v' switch is only supported from 1.7 onward... version = '1.6' proc = process.popen([mutool, '-v'], stdout=process.NULL, stderr=process.PIPE) try: output = proc.stderr.read() if output.startswith('mutool version '): version = output[15:].rstrip() finally: proc.stderr.close() proc.wait() version = LooseVersion(version) if version >= LooseVersion('1.8'): # Mutool executable with draw support. _mudraw_exec = [mutool, 'draw'] _mudraw_trace_args = ['-F', 'trace'] _pdf_possible = True else: # Separate mudraw executable. mudraw = process.find_executable((u'mudraw', )) if mudraw is None: log.debug('mudraw executable not found') else: _mudraw_exec = [mudraw] if version >= LooseVersion('1.7'): _mudraw_trace_args = ['-F', 'trace'] else: _mudraw_trace_args = ['-x'] _pdf_possible = True if _pdf_possible: log.info('Using MuPDF version: %s', version) log.debug('mutool: %s', ' '.join(_mutool_exec)) log.debug('mudraw: %s', ' '.join(_mudraw_exec)) log.debug('mudraw trace arguments: %s', ' '.join(_mudraw_trace_args)) else: log.info('MuPDF not available.') return _pdf_possible
def is_available(): global _pdf_possible if _pdf_possible is not None: return _pdf_possible mutool = process.find_executable(('mutool', )) _pdf_possible = False version = None if mutool is None: log.debug('mutool executable not found') else: _mutool_exec.append(mutool) # Find MuPDF version; assume 1.6 version since # the '-v' switch is only supported from 1.7 onward... version = (1, 6) with process.popen([mutool, '-v'], stdout=process.NULL, stderr=process.PIPE, universal_newlines=True) as proc: output = re.match( r'mutool version ' r'(?P<version>[\d.]+)([^\d].*)?', proc.stderr.read()) if output: version = tuple( map(int, output.group('version').split('.'))) if version >= (1, 8): # Mutool executable with draw support. _mudraw_exec.extend((mutool, 'draw', '-q')) _mudraw_trace_args.extend(('-F', 'trace')) _pdf_possible = True else: # Separate mudraw executable. mudraw = process.find_executable(('mudraw', )) if mudraw is None: log.debug('mudraw executable not found') else: _mudraw_exec.append(mudraw) if version >= (1, 7): _mudraw_trace_args.extend(('-F', 'trace')) else: _mudraw_trace_args.append('-x') _pdf_possible = True if _pdf_possible: log.info('Using MuPDF version: %s', '.'.join(map(str, version))) log.debug('mutool: %s', ' '.join(_mutool_exec)) log.debug('mudraw: %s', ' '.join(_mudraw_exec)) log.debug('mudraw trace arguments: %s', ' '.join(_mudraw_trace_args)) else: log.info('MuPDF not available.') return _pdf_possible
def is_available(): global _pdf_possible if _pdf_possible is not None: return _pdf_possible global _mutool_exec, _mudraw_exec, _mudraw_trace_args mutool = process.find_executable((u"mutool",)) _pdf_possible = False version = None if mutool is None: log.debug("mutool executable not found") else: _mutool_exec = [mutool] # Find MuPDF version; assume 1.6 version since # the '-v' switch is only supported from 1.7 onward... version = "1.6" proc = process.popen([mutool, "-v"], stdout=process.NULL, stderr=process.PIPE) try: output = proc.stderr.read() if output.startswith("mutool version "): version = output[15:].rstrip() finally: proc.stderr.close() proc.wait() version = LooseVersion(version) if version >= LooseVersion("1.8"): # Mutool executable with draw support. _mudraw_exec = [mutool, "draw"] _mudraw_trace_args = ["-F", "trace"] _pdf_possible = True else: # Separate mudraw executable. mudraw = process.find_executable((u"mudraw",)) if mudraw is None: log.debug("mudraw executable not found") else: _mudraw_exec = [mudraw] if version >= LooseVersion("1.7"): _mudraw_trace_args = ["-F", "trace"] else: _mudraw_trace_args = ["-x"] _pdf_possible = True if _pdf_possible: log.info("Using MuPDF version: %s", version) log.debug("mutool: %s", " ".join(_mutool_exec)) log.debug("mudraw: %s", " ".join(_mudraw_exec)) log.debug("mudraw trace arguments: %s", " ".join(_mudraw_trace_args)) else: log.info("MuPDF not available.") return _pdf_possible
def is_available(): global _pdf_possible if _pdf_possible is not None: return _pdf_possible mutool = process.find_executable(('mutool', )) _pdf_possible = False version = None if mutool is None: log.debug('mutool executable not found') else: _mutool_exec.append(mutool) # Find MuPDF version; assume 1.6 version since # the '-v' switch is only supported from 1.7 onward... version = '1.6' with process.popen([mutool, '-v'], stdout=process.NULL, stderr=process.PIPE, universal_newlines=True) as proc: output = proc.stderr.read() if output.startswith('mutool version '): version = output[15:].rstrip() version = LooseVersion(version) if version >= LooseVersion('1.8'): # Mutool executable with draw support. _mudraw_exec.extend((mutool, 'draw', '-q')) _mudraw_trace_args.extend(('-F', 'trace')) _pdf_possible = True else: # Separate mudraw executable. mudraw = process.find_executable(('mudraw', )) if mudraw is None: log.debug('mudraw executable not found') else: _mudraw_exec.append(mudraw) if version >= LooseVersion('1.7'): _mudraw_trace_args.extend(('-F', 'trace')) else: _mudraw_trace_args.append('-x') _pdf_possible = True if _pdf_possible: log.info('Using MuPDF version: %s', version) log.debug('mutool: %s', ' '.join(_mutool_exec)) log.debug('mudraw: %s', ' '.join(_mudraw_exec)) log.debug('mudraw trace arguments: %s', ' '.join(_mudraw_trace_args)) else: log.info('MuPDF not available.') return _pdf_possible
def _find_lha_executable(): """ Tries to start lha, and returns either 'lha' if it was started successfully or None otherwise. """ global _lha_executable if _lha_executable == -1: _lha_executable = process.find_executable((u'lha',)) return _lha_executable
def _find_unzip_executable(): """ Tries to run unzip, and returns 'unzip' on success. Returns None on failure. """ global _zip_executable if -1 == _zip_executable: _zip_executable = process.find_executable((u'unzip', )) return _zip_executable
def _find_7z_executable(): """ Tries to start 7z, and returns either '7z' if it was started successfully or None otherwise. """ global _7z_executable if _7z_executable == -1: _7z_executable = process.find_executable((u'7z', )) return _7z_executable
def _find_7z_executable(): """ Tries to start 7z, and returns either '7z' if it was started successfully or None otherwise. """ global _7z_executable if _7z_executable == -1: _7z_executable = process.find_executable((u'7z',)) return _7z_executable
def _find_unzip_executable(): """ Tries to run unzip, and returns 'unzip' on success. Returns None on failure. """ global _zip_executable if -1 == _zip_executable: _zip_executable = process.find_executable((u"unzip",)) return _zip_executable
def _find_lha_executable(): ''' Tries to start lha, and returns either 'lha' if it was started successfully or None otherwise. ''' global _lha_executable if _lha_executable == -1: _lha_executable = process.find_executable(('lha', )) return _lha_executable
def _find_unrar_executable(): """ Tries to start rar/unrar, and returns either 'rar' or 'unrar' if one of them was started successfully. Returns None if neither could be started. """ global _rar_executable if _rar_executable == -1: _rar_executable = process.find_executable((u'unrar', u'rar')) return _rar_executable
def is_executable(self, window): """ Check if a name is executable. This name can be either a relative path, when the executable is in PATH, or an absolute path. """ args = self.parse(window) if len(args) == 0: return False if self.is_valid_workdir(window): workdir = self.parse(window, text=self.get_cwd())[0] else: workdir = os.getcwd() exe = process.find_executable((args[0],), workdir=workdir) return exe is not None
def is_executable(self, window): ''' Check if a name is executable. This name can be either a relative path, when the executable is in PATH, or an absolute path. ''' args = self.parse(window) if len(args) == 0: return False if self.is_valid_workdir(window): workdir = self.parse(window, text=self.get_cwd())[0] else: workdir = os.getcwd() exe = process.find_executable((args[0], ), workdir=workdir) return exe is not None
def _find_unrar_executable(): ''' Tries to start rar/unrar, and returns either 'rar' or 'unrar' if one of them was started successfully. Returns None if neither could be started. ''' if 'path' not in _rar_executable: path = process.find_executable(('unrar-nonfree', 'unrar', 'rar'), is_valid_candidate=_is_not_unrar_free) _rar_executable['path'] = path if path is not None: with process.popen([path], text=True) as proc: # only check first line line = proc.stdout.read().strip().splitlines()[0].split() if line[0]=='UNRAR': log.debug('unrar version: %s', line[1]) return _rar_executable['path']
def _find_unrar_executable(): """ Tries to start rar/unrar, and returns either 'rar' or 'unrar' if one of them was started successfully. Returns None if neither could be started. """ global _rar_executable if _rar_executable == -1: if 'win32' == sys.platform: is_not_unrar_free = lambda exe: True else: def is_not_unrar_free(exe): real_exe = exe while os.path.islink(real_exe): real_exe = os.readlink(real_exe) if real_exe.endswith(os.path.sep + 'unrar-free'): log.warning( 'RAR executable %s is unrar-free, ignoring', exe) return False return True _rar_executable = process.find_executable( (u'unrar-nonfree', u'unrar', u'rar'), is_valid_candidate=is_not_unrar_free) return _rar_executable
def test_find_executable(self): cleanup = [] try: root_dir = tempfile.mkdtemp(dir=u'test', prefix=u'tmp.path.') # cleanup.append(lambda: shutil.rmtree(root_dir)) if 'win32' == sys.platform: orig_exe_dir = process._exe_dir cleanup.append( lambda: setattr(process, '_exe_dir', orig_exe_dir)) process._exe_dir = 'dir4' tree = ( ('bin1.exe', 'rx'), ('bin3.exe', 'rx'), ('dir1/bin1.exe', 'rx'), ('dir1/bin2', 'rx'), ('dir2/bin1.exe', 'rx'), ('dir3/bin2.exe', 'rx'), ('dir3/bin4.exe', 'rx'), ('dir3/dir/bin2.exe', 'rx'), ('dir4/bin4.exe', 'rx'), ('dir4/bin5.exe', 'rx'), ) tests = ( # Absolute path, unchanged. ([sys.executable], None, sys.executable), # Same without .exe extension. ([sys.executable[:-4]], None, sys.executable), # Must still be valid, though... (['C:/invalid/invalid'], None, None), # bin1 in workdir should be picked up. (['bin1.exe'], None, 'bin1.exe'), (['bad', 'bin1.exe'], None, 'bin1.exe'), # Same without .exe extension. (['bin1'], None, 'bin1.exe'), # bin2 in dir1 or bin2 @ind dir3 should not be picked up. (['bin2'], None, 'dir3/bin2.exe'), # Candidate with a directory component. (['./bin3'], None, 'bin3.exe'), # And a custom working directory. (['dir/bin2'], 'dir3', 'dir3/dir/bin2.exe'), # Check main executable directory is searched too. # (with higher priority than PATH) (['bin4'], None, 'dir4/bin4.exe'), # And work directory. (['bin4'], 'dir3', 'dir4/bin4.exe'), ) else: tree = ( ('bin1', 'rx'), ('bin3', 'rx'), ('dir1/bin1', 'rx'), ('dir1/bin2', 'r '), ('dir2/bin1', 'rx'), ('dir2/bin2', ' '), ('dir3/bin1', 'rx'), ('dir3/bin2', 'rx'), ('dir3/bin3', 'r '), ('dir3/bin4', 'rx'), ('dir3/dir/bin2', 'rx'), ('dir3/dir/bin3', 'rw '), ) tests = ( # Absolute path, unchanged. (['/bin/true'], None, '/bin/true'), # Must still be valid, though... (['/invalid/invalid'], None, None), # bin1 in workdir should not be picked up. (['bin1'], None, 'dir1/bin1'), # Check all candidates. (['bad', 'bin1'], None, 'dir1/bin1'), # bin2 in dir1 should not be picked up (not executable). (['bin2'], None, 'dir3/bin2'), # Same with bin3. (['bin3'], None, None), # Candidate with a directory component. (['./bin3'], None, 'bin3'), # And a custom working directory. (['dir/bin2'], 'dir3', 'dir3/dir/bin2'), # But must still be valid... (['dir/bin3'], 'dir3', None), ) _create_tree(root_dir, tree) root_dir = os.path.abspath(root_dir) orig_path = os.environ['PATH'] cleanup.append(lambda: os.environ.__setitem__('PATH', orig_path)) os.environ['PATH'] = os.pathsep.join('dir1 dir2 dir3'.split()) orig_cwd = os.getcwd() cleanup.append(lambda: os.chdir(orig_cwd)) os.chdir(root_dir) for candidates, workdir, expected in tests: if expected is not None: if not os.path.isabs(expected): expected = os.path.join(root_dir, expected) expected = os.path.normpath(expected) result = process.find_executable(candidates, workdir=workdir) msg = ('find_executable(%s, workdir=%s) failed; ' 'returned %s instead of %s' % ( candidates, workdir, result, expected, )) self.assertEqual(result, expected, msg=msg) finally: for fn in reversed(cleanup): fn()
from mcomix import i18n, process import tempfile import shutil import time import sys import os # Find fc-cache.exe fc_cache_exe = process.find_executable(( 'fc-cache', 'c:/Python27/Lib/site-packages/gnome/fc-cache.exe', )) # Update cache, while displaying a status dialog so the user know something is happening. def update(args=[], notification_delay=3, notification_duration=3): '''Update fontconfig cache by calling fc-cache.exe manually. The function will block until fc-cache.exe has finished. If the update takes more than <notification_delay> seconds, a notification window will be shown for at least <notification_duration> seconds. ''' cmd = [fc_cache_exe] cmd.extend(args) proc = process.popen(cmd, stdout=process.NULL) notif_time = time.time() + notification_delay
from mcomix import i18n, process import tempfile import shutil import time import sys import os # Find fc-cache.exe fc_cache_exe = process.find_executable(( 'fc-cache', 'c:/Python27/Lib/site-packages/gnome/fc-cache.exe', )) # Update cache, while displaying a status dialog so the user know something is happening. def update(args=[], notification_delay=3, notification_duration=3): '''Update fontconfig cache by calling fc-cache.exe manually. The function will block until fc-cache.exe has finished. If the update takes more than <notification_delay> seconds, a notification window will be shown for at least <notification_duration> seconds. ''' cmd = [fc_cache_exe] cmd.extend(args) proc = process.popen(cmd, stdout=process.NULL) notif_time = time.time() + notification_delay end_time = notif_time + notification_duration
stdout=process.NULL, stderr=process.PIPE, text=True) as proc: if output := re.match(r'mutool version (?P<version>[\d.]+)([^\d].*)?', proc.stderr.read()): _mupdf['version'] = tuple( map(int, output.group('version').split('.'))) if _mupdf['version'] >= (1, 8): # Mutool executable with draw support. _mupdf['found'] = True _mupdf['mudraw'].extend((mutool, 'draw', '-q')) _mupdf['mudraw_trace_args'].extend(('-F', 'trace')) return # Separate mudraw executable. if (mudraw := process.find_executable(('mudraw', ))) is None: return log.debug('mudraw executable not found') _mupdf['found'] = True _mupdf['mudraw'].append(mudraw) if _mupdf['version'] >= (1, 7): _mupdf['mudraw_trace_args'].extend(('-F', 'trace')) else: _mupdf['mudraw_trace_args'].append('-x') class PdfArchive(archive_base.BaseArchive): ''' Concurrent calls to extract welcome! ''' support_concurrent_extractions = True _fill_image_regex = re.compile( r'^\s*<fill_image\b.*\bmatrix="(?P<matrix>[^"]+)".*\bwidth="(?P<width>\d+)".*\bheight="(?P<height>\d+)".*/>\s*$'
def test_find_executable(self): cleanup = [] try: root_dir = tempfile.mkdtemp(dir=u'test', prefix=u'tmp.path.') # cleanup.append(lambda: shutil.rmtree(root_dir)) if 'win32' == sys.platform: orig_exe_dir = process._exe_dir cleanup.append(lambda: setattr(process, '_exe_dir', orig_exe_dir)) process._exe_dir = 'dir4' tree = ( ('bin1.exe' , 'rx'), ('bin3.exe' , 'rx'), ('dir1/bin1.exe' , 'rx'), ('dir1/bin2' , 'rx'), ('dir2/bin1.exe' , 'rx'), ('dir3/bin2.exe' , 'rx'), ('dir3/bin4.exe' , 'rx'), ('dir3/dir/bin2.exe', 'rx'), ('dir4/bin4.exe' , 'rx'), ('dir4/bin5.exe' , 'rx'), ) tests = ( # Absolute path, unchanged. ([sys.executable] , None , sys.executable ), # Same without .exe extension. ([sys.executable[:-4]] , None , sys.executable ), # Must still be valid, though... (['C:/invalid/invalid'], None , None ), # bin1 in workdir should be picked up. (['bin1.exe'] , None , 'bin1.exe' ), (['bad', 'bin1.exe'] , None , 'bin1.exe' ), # Same without .exe extension. (['bin1'] , None , 'bin1.exe' ), # bin2 in dir1 or bin2 @ind dir3 should not be picked up. (['bin2'] , None , 'dir3/bin2.exe' ), # Candidate with a directory component. (['./bin3'] , None , 'bin3.exe' ), # And a custom working directory. (['dir/bin2'] , 'dir3', 'dir3/dir/bin2.exe'), # Check main executable directory is searched too. # (with higher priority than PATH) (['bin4'] , None , 'dir4/bin4.exe' ), # And work directory. (['bin4'] , 'dir3', 'dir4/bin4.exe' ), ) else: tree = ( ('bin1' , 'rx'), ('bin3' , 'rx'), ('dir1/bin1' , 'rx'), ('dir1/bin2' , 'r '), ('dir2/bin1' , 'rx'), ('dir2/bin2' , ' '), ('dir3/bin1' , 'rx'), ('dir3/bin2' , 'rx'), ('dir3/bin3' , 'r '), ('dir3/bin4' , 'rx'), ('dir3/dir/bin2', 'rx'), ('dir3/dir/bin3', 'rw '), ) tests = ( # Absolute path, unchanged. (['/bin/true'] , None , '/bin/true' ), # Must still be valid, though... (['/invalid/invalid'], None , None ), # bin1 in workdir should not be picked up. (['bin1'] , None , 'dir1/bin1' ), # Check all candidates. (['bad', 'bin1'] , None , 'dir1/bin1' ), # bin2 in dir1 should not be picked up (not executable). (['bin2'] , None , 'dir3/bin2' ), # Same with bin3. (['bin3'] , None , None ), # Candidate with a directory component. (['./bin3'] , None , 'bin3' ), # And a custom working directory. (['dir/bin2'] , 'dir3', 'dir3/dir/bin2'), # But must still be valid... (['dir/bin3'] , 'dir3', None ), ) _create_tree(root_dir, tree) root_dir = os.path.abspath(root_dir) orig_path = os.environ['PATH'] cleanup.append(lambda: os.environ.__setitem__('PATH', orig_path)) os.environ['PATH'] = os.pathsep.join('dir1 dir2 dir3'.split()) orig_cwd = os.getcwd() cleanup.append(lambda: os.chdir(orig_cwd)) os.chdir(root_dir) for candidates, workdir, expected in tests: if expected is not None: if not os.path.isabs(expected): expected = os.path.join(root_dir, expected) expected = os.path.normpath(expected) result = process.find_executable(candidates, workdir=workdir) msg = ( 'find_executable(%s, workdir=%s) failed; ' 'returned %s instead of %s' % ( candidates, workdir, result, expected, ) ) self.assertEqual(result, expected, msg=msg) finally: for fn in reversed(cleanup): fn()
def run(): """Run the program.""" try: import pkg_resources except ImportError: # gettext isn't initialized yet, since pkg_resources is required to find translation files. # Thus, localizing these messages is pointless. log._print("The package 'pkg_resources' could not be found.") log._print("You need to install the 'setuptools' package, which also includes pkg_resources.") log._print("Note: On most distributions, 'distribute' supersedes 'setuptools'.") wait_and_exit() # Load configuration and setup localisation. preferences.read_preferences_file() from mcomix import i18n i18n.install_gettext() # Retrieve and parse command line arguments. argv = portability.get_commandline_args() opts, args = parse_arguments(argv) # First things first: set the log level. log.setLevel(opts.loglevel) # On Windows, update the fontconfig cache manually, before MComix starts # using Gtk, since the process may take several minutes, during which the # main window will just be frozen if the work is left to Gtk itself... if opts.update_fontconfig_cache: # First, update fontconfig cache. log.debug('starting fontconfig cache update') try: from mcomix.win32 import fc_cache from mcomix import process fc_cache.update() log.debug('fontconfig cache updated') except Exception as e: log.error('during fontconfig cache update', exc_info=e) # And then replace current MComix process with a fresh one # (that will not try to update the cache again). exe = sys.argv[0] if sys.platform == 'win32' and exe.endswith('.py'): # Find the interpreter. exe = process.find_executable(('pythonw.exe', 'python.exe')) args = [exe, sys.argv[0]] else: args = [exe] if sys.platform == 'win32': args.append('--no-update-fontconfig-cache') args.extend(argv) if '--update-fontconfig-cache' in args: args.remove('--update-fontconfig-cache') log.debug('restarting MComix from fresh: os.execv(%s, %s)', repr(exe), args) try: if sys.platform == 'win32': # Of course we can't use os.execv on Windows because it will # mangle arguments containing spaces or non-ascii characters... process.Win32Popen(args) sys.exit(0) else: os.execv(exe, args) except Exception as e: log.error('os.execv(%s, %s) failed', exe, str(args), exc_info=e) wait_and_exit() # Check for PyGTK and PIL dependencies. try: import pygtk pygtk.require('2.0') import gtk assert gtk.gtk_version >= (2, 12, 0) assert gtk.pygtk_version >= (2, 12, 0) import gobject gobject.threads_init() except AssertionError: log.error( _("You do not have the required versions of GTK+ and PyGTK installed.") ) log.error( _('Installed GTK+ version is: %s') % \ '.'.join([str(n) for n in gtk.gtk_version]) ) log.error( _('Required GTK+ version is: 2.12.0 or higher') ) log.error( _('Installed PyGTK version is: %s') % \ '.'.join([str(n) for n in gtk.pygtk_version]) ) log.error( _('Required PyGTK version is: 2.12.0 or higher') ) wait_and_exit() except ImportError: log.error( _('Required PyGTK version is: 2.12.0 or higher') ) log.error( _('No version of PyGTK was found on your system.') ) log.error( _('This error might be caused by missing GTK+ libraries.') ) wait_and_exit() try: import PIL.Image assert PIL.Image.VERSION >= '1.1.5' except AssertionError: log.error( _("You don't have the required version of the Python Imaging"), end=' ') log.error( _('Library (PIL) installed.') ) log.error( _('Installed PIL version is: %s') % Image.VERSION ) log.error( _('Required PIL version is: 1.1.5 or higher') ) wait_and_exit() except ImportError: log.error( _('Python Imaging Library (PIL) 1.1.5 or higher is required.') ) log.error( _('No version of the Python Imaging Library was found on your system.') ) wait_and_exit() if not os.path.exists(constants.DATA_DIR): os.makedirs(constants.DATA_DIR, 0700) if not os.path.exists(constants.CONFIG_DIR): os.makedirs(constants.CONFIG_DIR, 0700) from mcomix import icons icons.load_icons() open_path = None open_page = 1 if len(args) == 1: open_path = args[0] elif len(args) > 1: open_path = args elif preferences.prefs['auto load last file'] \ and preferences.prefs['path to last file'] \ and os.path.isfile(preferences.prefs['path to last file']): open_path = preferences.prefs['path to last file'] open_page = preferences.prefs['page of last file'] # Some languages require a RTL layout if preferences.prefs['language'] in ('he', 'fa'): gtk.widget_set_default_direction(gtk.TEXT_DIR_RTL) gtk.gdk.set_program_class(constants.APPNAME) from mcomix import main window = main.MainWindow(fullscreen = opts.fullscreen, is_slideshow = opts.slideshow, show_library = opts.library, manga_mode = opts.manga, double_page = opts.doublepage, zoom_mode = opts.zoommode, open_path = open_path, open_page = open_page) main.set_main_window(window) if 'win32' != sys.platform: # Add a SIGCHLD handler to reap zombie processes. def on_sigchld(signum, frame): try: os.waitpid(-1, os.WNOHANG) except OSError: pass signal.signal(signal.SIGCHLD, on_sigchld) signal.signal(signal.SIGTERM, lambda: gobject.idle_add(window.terminate_program)) try: gtk.main() except KeyboardInterrupt: # Will not always work because of threading. window.terminate_program()
def _find_7z_executable(): ''' Tries to start 7z, and returns either '7z' if it was started successfully or None otherwise. ''' if 'path' not in _7z_executable: _7z_executable['path'] = process.find_executable(('7z', )) return _7z_executable['path']