Merge pull request #6 from gnome-terminator/python3

Implement support for Python 3
This commit is contained in:
Markus Frosch 2020-04-05 19:54:57 +02:00 committed by GitHub
commit c0007818bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 353 additions and 4309 deletions

View File

@ -7,9 +7,6 @@ terminator.py
data/terminator.desktop.in
data/terminator.appdata.xml.in
terminatorlib/borg.py
terminatorlib/configobj/configobj.py
terminatorlib/configobj/__init__.py
terminatorlib/configobj/validate.py
terminatorlib/config.py
terminatorlib/container.py
terminatorlib/cwd.py

View File

@ -1,4 +1,5 @@
#!/usr/bin/env python2
#!/usr/bin/env python
#
# remotinator - send commands to Terminator via DBus
# Copyright (C) 2006-2010 cmsj@tenshu.net
#

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python
from distutils.core import setup
from distutils.dist import Distribution
@ -53,8 +53,8 @@ class BuildData(build):
try:
rc = subprocess.call(['msgfmt', '-o', mo, po])
if rc != 0:
raise Warning, "msgfmt returned %d" % rc
except Exception, e:
raise Warning("msgfmt returned %d" % rc)
except Exception as e:
error("Building gettext files failed. Ensure you have gettext installed. Alternatively, try setup.py --without-gettext [build|install]")
error("Error: %s" % str(e))
sys.exit(1)
@ -104,7 +104,7 @@ class Uninstall(Command):
raise DistutilsFileError("Pass manifest with --manifest=file")
f = open(self.manifest)
files = [file.strip() for file in f]
except IOError, e:
except IOError as e:
raise DistutilsFileError("unable to open install manifest: %s", str(e))
finally:
if f:
@ -116,7 +116,7 @@ class Uninstall(Command):
if not self.dry_run:
try:
os.unlink(file)
except OSError, e:
except OSError as e:
warn("could not delete: %s" % repr(file))
elif not os.path.isdir(file):
info("skipping %s" % repr(file))
@ -133,7 +133,7 @@ class Uninstall(Command):
if not self.dry_run:
try:
os.rmdir(dir)
except OSError, e:
except OSError as e:
warn("could not remove directory: %s" % str(e))
else:
info("skipping empty directory %s" % repr(dir))
@ -152,7 +152,7 @@ class InstallData(install_data):
info("running gtk-update-icon-cache")
try:
subprocess.call(["gtk-update-icon-cache", "-q", "-f", "-t", os.path.join(self.install_dir, "share/icons/hicolor")])
except Exception, e:
except Exception as e:
warn("updating the GTK icon cache failed: %s" % str(e))
def _find_mo_files (self):
@ -231,7 +231,6 @@ setup(name=APP_NAME,
],
packages=[
'terminatorlib',
'terminatorlib.configobj',
'terminatorlib.plugins',
],
install_requires=[

View File

@ -1,4 +1,5 @@
#!/usr/bin/env python2
#!/usr/bin/env python
#
# Terminator - multiple gnome terminals in one window
# Copyright (C) 2006-2010 cmsj@tenshu.net
#
@ -92,7 +93,7 @@ if __name__ == '__main__':
if OPTIONS.working_directory is None:
OPTIONS.working_directory = ORIGCWD
optionslist = {}
for opt, val in OPTIONS.__dict__.items():
for opt, val in list(OPTIONS.__dict__.items()):
if type(val) == type([]):
val = ' '.join(val)
if val == True:
@ -120,12 +121,12 @@ if __name__ == '__main__':
try:
dbg('Creating a terminal with layout: %s' % OPTIONS.layout)
TERMINATOR.create_layout(OPTIONS.layout)
except (KeyError,ValueError), ex:
except (KeyError,ValueError) as ex:
err('layout creation failed, creating a window ("%s")' % ex)
TERMINATOR.new_window()
TERMINATOR.layout_done()
if OPTIONS.debug >= 2:
if OPTIONS.debug and OPTIONS.debug >= 2:
import terminatorlib.debugserver as debugserver
# pylint: disable-msg=W0611
import threading

View File

@ -1,6 +1,5 @@
#!/usr/bin/env python2
# Terminator - multiple gnome terminals in one window
# Copyright (C) 2006-2010 cmsj@tenshu.net
# Terminator - multiple gnome terminals in one window
# Copyright (C) 2006-2010 cmsj@tenshu.net
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

5
terminatorlib/borg.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only
"""borg.py - We are the borg. Resistance is futile.
@ -9,7 +8,7 @@ exist to encourage re-use, but I can not find any
specific licencing terms.
"""
from util import dbg
from .util import dbg
# pylint: disable-msg=R0903
# pylint: disable-msg=R0921
@ -43,7 +42,7 @@ class Borg:
type."""
if borgtype is None:
raise TypeError('Borg::__init__: You must pass a borgtype')
if not self.__shared_state.has_key(borgtype):
if borgtype not in self.__shared_state:
dbg('Borg::__init__: Preparing borg state for %s' % borgtype)
self.__shared_state[borgtype] = {}
self.__dict__ = self.__shared_state[borgtype]

73
terminatorlib/config.py Executable file → Normal file
View File

@ -1,6 +1,5 @@
#!/usr/bin/env python2
# TerminatorConfig - layered config classes
# Copyright (C) 2006-2010 cmsj@tenshu.net
# TerminatorConfig - layered config classes
# Copyright (C) 2006-2010 cmsj@tenshu.net
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -71,13 +70,12 @@ KeyError: 'ConfigBase::get_item: unknown key algo'
"""
import platform
import os
from copy import copy
from configobj.configobj import ConfigObj, flatten_errors
from configobj.validate import Validator
from borg import Borg
from util import dbg, err, DEBUG, get_config_dir, dict_diff
from configobj import ConfigObj, flatten_errors
from validate import Validator
from .borg import Borg
from .util import dbg, err, DEBUG, get_config_dir, dict_diff
from gi.repository import Gio
@ -298,7 +296,7 @@ class Config(object):
profile = options.profile
dbg('Config::set_profile: Changing profile to %s' % profile)
self.profile = profile
if not self.base.profiles.has_key(profile):
if profile not in self.base.profiles:
dbg('Config::set_profile: %s does not exist, creating' % profile)
self.base.profiles[profile] = copy(DEFAULTS['profiles']['default'])
@ -313,7 +311,7 @@ class Config(object):
# remove a profile
err('Config::del_profile: Deleting in-use profile %s.' % profile)
self.set_profile('default')
if self.base.profiles.has_key(profile):
if profile in self.base.profiles:
del(self.base.profiles[profile])
options = self.options_get()
if options and options.profile == profile:
@ -322,7 +320,7 @@ class Config(object):
def rename_profile(self, profile, newname):
"""Rename a profile"""
if self.base.profiles.has_key(profile):
if profile in self.base.profiles:
self.base.profiles[newname] = self.base.profiles[profile]
del(self.base.profiles[profile])
if profile == self.profile:
@ -330,7 +328,7 @@ class Config(object):
def list_profiles(self):
"""List all configured profiles"""
return(self.base.profiles.keys())
return(list(self.base.profiles.keys()))
def add_layout(self, name, layout):
"""Add a new layout"""
@ -342,18 +340,18 @@ class Config(object):
def del_layout(self, layout):
"""Delete a layout"""
if self.base.layouts.has_key(layout):
if layout in self.base.layouts:
del(self.base.layouts[layout])
def rename_layout(self, layout, newname):
"""Rename a layout"""
if self.base.layouts.has_key(layout):
if layout in self.base.layouts:
self.base.layouts[newname] = self.base.layouts[layout]
del(self.base.layouts[layout])
def list_layouts(self):
"""List all configured layouts"""
return(self.base.layouts.keys())
return(list(self.base.layouts.keys()))
def connect_gsetting_callbacks(self):
"""Get system settings and create callbacks for changes"""
@ -416,7 +414,7 @@ class Config(object):
self.system_mono_font = None
# Need to trigger a reconfigure to change active terminals immediately
if "Terminator" not in globals():
from terminator import Terminator
from .terminator import Terminator
Terminator().reconfigure()
def save(self):
@ -490,7 +488,7 @@ class ConfigBase(Borg):
Borg.__init__(self, self.__class__.__name__)
self.prepare_attributes()
import optionparse
from . import optionparse
self.command_line_options = optionparse.options
self.load()
@ -585,7 +583,7 @@ class ConfigBase(Borg):
configspec = ConfigObj(configspecdata)
if DEBUG == True:
configspec.write(open('/tmp/terminator_configspec_debug.txt', 'w'))
configspec.write(open('/tmp/terminator_configspec_debug.txt', 'wb'))
return(configspec)
def load(self):
@ -604,7 +602,7 @@ class ConfigBase(Borg):
dbg('looking for config file: %s' % filename)
try:
configfile = open(filename, 'r')
except Exception, ex:
except Exception as ex:
if not self.whined:
err('ConfigBase::load: Unable to open %s (%s)' % (filename, ex))
self.whined = True
@ -617,7 +615,7 @@ class ConfigBase(Borg):
parser = ConfigObj(configfile, configspec=configspec)
validator = Validator()
result = parser.validate(validator, preserve_errors=True)
except Exception, ex:
except Exception as ex:
err('Unable to load configuration: %s' % ex)
return
@ -637,12 +635,12 @@ class ConfigBase(Borg):
if section_name == 'profiles':
for profile in parser[section_name]:
dbg('ConfigBase::load: Processing profile: %s' % profile)
if not section.has_key(section_name):
if section_name not in section:
# FIXME: Should this be outside the loop?
section[profile] = copy(DEFAULTS['profiles']['default'])
section[profile].update(parser[section_name][profile])
elif section_name == 'plugins':
if not parser.has_key(section_name):
if section_name not in parser:
continue
for part in parser[section_name]:
dbg('ConfigBase::load: Processing %s: %s' % (section_name,
@ -657,7 +655,7 @@ class ConfigBase(Borg):
continue
section[layout] = parser[section_name][layout]
elif section_name == 'keybindings':
if not parser.has_key(section_name):
if section_name not in parser:
continue
for part in parser[section_name]:
dbg('ConfigBase::load: Processing %s: %s' % (section_name,
@ -669,7 +667,7 @@ class ConfigBase(Borg):
else:
try:
section.update(parser[section_name])
except KeyError, ex:
except KeyError as ex:
dbg('ConfigBase::load: skipping missing section %s' %
section_name)
@ -683,7 +681,7 @@ class ConfigBase(Borg):
def save(self):
"""Save the config to a file"""
dbg('ConfigBase::save: saving config')
parser = ConfigObj()
parser = ConfigObj(encoding='utf-8')
parser.indent_type = ' '
for section_name in ['global_config', 'keybindings']:
@ -711,21 +709,26 @@ class ConfigBase(Borg):
if not os.path.isdir(config_dir):
os.makedirs(config_dir)
try:
parser.write(open(self.command_line_options.config, 'w'))
except Exception, ex:
temp_file = self.command_line_options.config + '.tmp'
with open(temp_file, 'wb') as fh:
parser.write(fh)
os.rename(temp_file, self.command_line_options.config)
except Exception as ex:
err('ConfigBase::save: Unable to save config: %s' % ex)
def get_item(self, key, profile='default', plugin=None, default=None):
"""Look up a configuration item"""
if not self.profiles.has_key(profile):
if profile not in self.profiles:
# Hitting this generally implies a bug
profile = 'default'
if self.global_config.has_key(key):
if key in self.global_config:
dbg('ConfigBase::get_item: %s found in globals: %s' %
(key, self.global_config[key]))
return(self.global_config[key])
elif self.profiles[profile].has_key(key):
elif key in self.profiles[profile]:
dbg('ConfigBase::get_item: %s found in profile %s: %s' % (
key, profile, self.profiles[profile][key]))
return(self.profiles[profile][key])
@ -745,14 +748,14 @@ class ConfigBase(Borg):
dbg('ConfigBase::set_item: Setting %s=%s (profile=%s, plugin=%s)' %
(key, value, profile, plugin))
if self.global_config.has_key(key):
if key in self.global_config:
self.global_config[key] = value
elif self.profiles[profile].has_key(key):
elif key in self.profiles[profile]:
self.profiles[profile][key] = value
elif key == 'keybindings':
self.keybindings = value
elif plugin is not None:
if not self.plugins.has_key(plugin):
if plugin not in self.plugins:
self.plugins[plugin] = {}
self.plugins[plugin][key] = value
else:
@ -762,7 +765,7 @@ class ConfigBase(Borg):
def get_plugin(self, plugin):
"""Return a whole tree for a plugin"""
if self.plugins.has_key(plugin):
if plugin in self.plugins:
return(self.plugins[plugin])
def set_plugin(self, plugin, tree):
@ -797,7 +800,7 @@ class ConfigBase(Borg):
def get_layout(self, layout):
"""Return a layout"""
if self.layouts.has_key(layout):
if layout in self.layouts:
return(self.layouts[layout])
else:
err('layout does not exist: %s' % layout)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

13
terminatorlib/container.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only
"""container.py - classes necessary to contain Terminal widgets"""
@ -6,11 +5,11 @@
from gi.repository import GObject
from gi.repository import Gtk
from factory import Factory
from config import Config
from util import dbg, err
from translation import _
from signalman import Signalman
from .factory import Factory
from .config import Config
from .util import dbg, err
from .translation import _
from .signalman import Signalman
# pylint: disable-msg=R0921
class Container(object):
@ -283,7 +282,7 @@ the tab will also close all terminals within it.')
if mytype == 'Notebook':
labels = []
last_active_term = []
for tabnum in xrange(0, self.get_n_pages()):
for tabnum in range(0, self.get_n_pages()):
page = self.get_nth_page(tabnum)
label = self.get_tab_label(page)
labels.append(label.get_custom_label())

7
terminatorlib/cwd.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only
"""cwd.py - function necessary to get the cwd for a given pid on various OSes
@ -15,7 +14,7 @@
import platform
import os
import pwd
from util import dbg, err
from .util import dbg, err
try:
import psutil
@ -46,7 +45,7 @@ def get_pid_cwd():
func = linux_get_pid_cwd
elif system == 'FreeBSD':
try:
import freebsd
from . import freebsd
func = freebsd.get_process_cwd
dbg('Using FreeBSD get_pid_cwd')
except (OSError, NotImplementedError, ImportError):
@ -66,7 +65,7 @@ def proc_get_pid_cwd(pid, path):
insert it into, e.g. /proc/%s/cwd"""
try:
cwd = os.path.realpath(path % pid)
except Exception, ex:
except Exception as ex:
err('Unable to get cwd for PID %s: %s' % (pid, ex))
cwd = '/'

View File

@ -1,5 +1,3 @@
#!/usr/bin/env python2
#
# Copyright (c) 2008, Thomas Hurst <tom@hur.st>
#
# Use of this file is unrestricted provided this notice is retained.
@ -10,7 +8,7 @@ from terminatorlib.version import APP_NAME, APP_VERSION
import socket
import threading
import SocketServer
import socketserver
import code
import sys
import readline
@ -22,7 +20,7 @@ def ddbg(msg):
return
dbg(msg)
class PythonConsoleServer(SocketServer.BaseRequestHandler):
class PythonConsoleServer(socketserver.BaseRequestHandler):
env = None
def setup(self):
dbg('debugserver: connect from %s' % str(self.client_address))
@ -165,7 +163,7 @@ class TerminatorConsole(code.InteractiveConsole):
def spawn(env):
PythonConsoleServer.env = env
tcpserver = SocketServer.TCPServer(('127.0.0.1', 0), PythonConsoleServer)
tcpserver = socketserver.TCPServer(('127.0.0.1', 0), PythonConsoleServer)
dbg("debugserver: listening on %s" % str(tcpserver.server_address))
debugserver = threading.Thread(target=tcpserver.serve_forever, name="DebugServer")
debugserver.setDaemon(True)

View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab
#
# Copyright (c) 2009, Emmanuel Bretelle <chantra@debuntu.org>

View File

@ -1,6 +1,5 @@
#!/usr/bin/env python2
# TerminatorEncoding - charset encoding classes
# Copyright (C) 2006-2010 chantra@debuntu.org
# TerminatorEncoding - charset encoding classes
# Copyright (C) 2006-2010 chantra@debuntu.org
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -23,7 +22,7 @@ This list is taken from gnome-terminal's src/terminal-encoding.c
and src/encoding.c
"""
from translation import _
from .translation import _
#pylint: disable-msg=R0903
class TerminatorEncoding:

17
terminatorlib/factory.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only
"""factory.py - Maker of objects
@ -19,8 +18,8 @@ True
"""
from borg import Borg
from util import dbg, err, inject_uuid
from .borg import Borg
from .util import dbg, err, inject_uuid
# pylint: disable-msg=R0201
# pylint: disable-msg=W0613
@ -33,7 +32,7 @@ class Factory(Borg):
'Notebook': 'notebook',
'Container': 'container',
'Window': 'window'}
types_keys = types.keys()
types_keys = list(types.keys())
instance_types = {}
instance_types_keys = []
@ -97,26 +96,26 @@ class Factory(Borg):
def make_window(self, **kwargs):
"""Make a Window"""
import window
from . import window
return(window.Window(**kwargs))
def make_terminal(self, **kwargs):
"""Make a Terminal"""
import terminal
from . import terminal
return(terminal.Terminal())
def make_hpaned(self, **kwargs):
"""Make an HPaned"""
import paned
from . import paned
return(paned.HPaned())
def make_vpaned(self, **kwargs):
"""Make a VPaned"""
import paned
from . import paned
return(paned.VPaned())
def make_notebook(self, **kwargs):
"""Make a Notebook"""
import notebook
from . import notebook
return(notebook.Notebook(kwargs['window']))

12
terminatorlib/freebsd.py Normal file → Executable file
View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python
#
# Copyright (c) 2008, Thomas Hurst <tom@hur.st>
#
@ -50,11 +50,11 @@ uintlen = c_size_t(sizeof(c_uint))
ver = c_uint(0)
if (libc.sysctlbyname('kern.osreldate', byref(ver), byref(uintlen), None, 0) < 0):
raise OSError, "sysctlbyname returned < 0"
raise OSError("sysctlbyname returned < 0")
# kern.proc.filedesc added for procstat(1) after these __FreeBSD_versions
if ver.value < 700104 and ver.value < 800019:
raise NotImplementedError, "cwd detection requires a recent 7.0-STABLE or 8-CURRENT"
raise NotImplementedError("cwd detection requires a recent 7.0-STABLE or 8-CURRENT")
def get_process_cwd(pid):
@ -72,7 +72,7 @@ def get_process_cwd(pid):
return None
kifs = cast(buf, POINTER(kinfo_file))
for i in xrange(0, uintlen.value / sizeof(kinfo_file)):
for i in range(0, uintlen.value / sizeof(kinfo_file)):
kif = kifs[i]
if kif.kf_fd == -1: # KF_FD_TYPE_CWD
return kif.kf_path
@ -80,12 +80,12 @@ def get_process_cwd(pid):
if __name__ == '__main__':
import os, sys
print " => %d cwd = %s" % (os.getpid(), get_process_cwd(os.getpid()))
print(" => %d cwd = %s" % (os.getpid(), get_process_cwd(os.getpid())))
for pid in sys.argv:
try:
pid = int(pid)
except:
pass
else:
print " => %d cwd = %s" % (pid, get_process_cwd(pid))
print(" => %d cwd = %s" % (pid, get_process_cwd(pid)))

View File

@ -1,17 +1,17 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only
"""ipc.py - DBus server and API calls"""
import hashlib
from gi.repository import Gdk
import dbus.service
from dbus.exceptions import DBusException
import dbus.glib
from borg import Borg
from terminator import Terminator
from config import Config
from factory import Factory
from util import dbg, enumerate_descendants
from .borg import Borg
from .terminator import Terminator
from .config import Config
from .factory import Factory
from .util import dbg, enumerate_descendants
CONFIG = Config()
if not CONFIG['dbus']:
@ -23,7 +23,9 @@ BUS_BASE = 'net.tenshu.Terminator2'
BUS_PATH = '/net/tenshu/Terminator2'
try:
# Try and include the X11 display name in the dbus bus name
DISPLAY = hex(hash(Gdk.get_display().partition('.')[0]))
DISPLAY = Gdk.get_display().partition('.')[0]
# In Python 3, hash() uses a different seed on each run, so use hashlib
DISPLAY = hashlib.md5(DISPLAY.encode('utf-8')).hexdigest()
BUS_NAME = '%s%s' % (BUS_BASE, DISPLAY)
except:
BUS_NAME = BUS_BASE
@ -185,7 +187,7 @@ class DBusService(Borg, dbus.service.Object):
def with_proxy(func):
"""Decorator function to connect to the session dbus bus"""
dbg('dbus client call: %s' % func.func_name)
dbg('dbus client call: %s' % func.__name__)
def _exec(*args, **argd):
bus = dbus.SessionBus()
proxy = bus.get_object(BUS_NAME, BUS_PATH)
@ -205,45 +207,45 @@ def new_tab_cmdline(session, options):
@with_proxy
def new_window(session, options):
"""Call the dbus method to open a new window"""
print session.new_window()
print(session.new_window())
@with_proxy
def new_tab(session, uuid, options):
"""Call the dbus method to open a new tab in the first window"""
print session.new_tab(uuid)
print(session.new_tab(uuid))
@with_proxy
def hsplit(session, uuid, options):
"""Call the dbus method to horizontally split a terminal"""
print session.hsplit(uuid)
print(session.hsplit(uuid))
@with_proxy
def vsplit(session, uuid, options):
"""Call the dbus method to vertically split a terminal"""
print session.vsplit(uuid)
print(session.vsplit(uuid))
@with_proxy
def get_terminals(session, options):
"""Call the dbus method to return a list of all terminals"""
print '\n'.join(session.get_terminals())
print('\n'.join(session.get_terminals()))
@with_proxy
def get_window(session, uuid, options):
"""Call the dbus method to return the toplevel tab for a terminal"""
print session.get_window(uuid)
print(session.get_window(uuid))
@with_proxy
def get_window_title(session, uuid, options):
"""Call the dbus method to return the title of a tab"""
print session.get_window_title(uuid)
print(session.get_window_title(uuid))
@with_proxy
def get_tab(session, uuid, options):
"""Call the dbus method to return the toplevel tab for a terminal"""
print session.get_tab(uuid)
print(session.get_tab(uuid))
@with_proxy
def get_tab_title(session, uuid, options):
"""Call the dbus method to return the title of a tab"""
print session.get_tab_title(uuid)
print(session.get_tab_title(uuid))

View File

@ -1,6 +1,5 @@
#!/usr/bin/env python2
# Terminator - multiple gnome terminals in one window
# Copyright (C) 2006-2010 cmsj@tenshu.net
# Terminator - multiple gnome terminals in one window
# Copyright (C) 2006-2010 cmsj@tenshu.net
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -24,7 +23,7 @@ keyboard shortcuts.
import re
from gi.repository import Gtk, Gdk
from util import err
from .util import err
class KeymapError(Exception):
"""Custom exception for errors in keybinding configurations"""
@ -61,7 +60,7 @@ class Keybindings:
"""Parse bindings and mangle into an appropriate form"""
self._lookup = {}
self._masks = 0
for action, bindings in self.keys.items():
for action, bindings in list(self.keys.items()):
if not isinstance(bindings, tuple):
bindings = (bindings,)

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python
# Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only
"""layoutlauncher.py - class for the Layout Launcher window"""
@ -7,11 +7,11 @@ import os
from gi.repository import Gtk
from gi.repository import GObject
from util import dbg, err, spawn_new_terminator
import config
from translation import _
from terminator import Terminator
from plugin import PluginRegistry
from .util import dbg, err, spawn_new_terminator
from . import config
from .translation import _
from .terminator import Terminator
from .plugin import PluginRegistry
class LayoutLauncher:
"""Class implementing the various parts of the preferences editor"""
@ -38,9 +38,9 @@ class LayoutLauncher:
librarypath = os.path.join(head, 'layoutlauncher.glade')
gladefile = open(librarypath, 'r')
gladedata = gladefile.read()
except Exception, ex:
print "Failed to find layoutlauncher.glade"
print ex
except Exception as ex:
print("Failed to find layoutlauncher.glade")
print(ex)
return
self.builder.add_from_string(gladedata)
@ -72,7 +72,7 @@ class LayoutLauncher:
"""Update the contents of the layout"""
self.layouttreestore.clear()
layouts = self.config.list_layouts()
for layout in sorted(layouts, cmp=lambda x,y: cmp(x.lower(), y.lower())):
for layout in sorted(layouts, key=str.lower):
if layout != "default":
self.layouttreestore.append([layout])
else:
@ -100,9 +100,9 @@ class LayoutLauncher:
spawn_new_terminator(self.terminator.origcwd, ['-u', '-l', layout])
if __name__ == '__main__':
import util
from . import util
util.DEBUG = True
import terminal
from . import terminal
LAYOUTLAUNCHER = LayoutLauncher()
Gtk.main()

44
terminatorlib/notebook.py Executable file → Normal file
View File

@ -1,20 +1,20 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only
"""notebook.py - classes for the notebook widget"""
from functools import cmp_to_key
from gi.repository import GObject
from gi.repository import Gtk
from gi.repository import Gdk
from gi.repository import Gio
from terminator import Terminator
from config import Config
from factory import Factory
from container import Container
from editablelabel import EditableLabel
from translation import _
from util import err, dbg, enumerate_descendants, make_uuid
from .terminator import Terminator
from .config import Config
from .factory import Factory
from .container import Container
from .editablelabel import EditableLabel
from .translation import _
from .util import err, dbg, enumerate_descendants, make_uuid
class Notebook(Container, Gtk.Notebook):
"""Class implementing a Gtk.Notebook container"""
@ -65,7 +65,7 @@ class Notebook(Container, Gtk.Notebook):
pos = getattr(Gtk.PositionType, self.config['tab_position'].upper())
self.set_tab_pos(pos)
for tab in xrange(0, self.get_n_pages()):
for tab in range(0, self.get_n_pages()):
label = self.get_tab_label(self.get_nth_page(tab))
label.update_angle()
@ -88,7 +88,7 @@ class Notebook(Container, Gtk.Notebook):
if (order_a > order_b):
return 1
if not layout.has_key('children'):
if 'children' not in layout:
err('layout specifies no children: %s' % layout)
return
@ -99,8 +99,8 @@ class Notebook(Container, Gtk.Notebook):
return
num = 0
keys = children.keys()
keys.sort(child_compare)
keys = list(children.keys())
keys = sorted(keys, key=cmp_to_key(child_compare))
for child_key in keys:
child = children[child_key]
@ -122,7 +122,7 @@ class Notebook(Container, Gtk.Notebook):
# This page does not yet exist, so make it
self.newtab(children[child_key])
page = self.get_nth_page(num)
if layout.has_key('labels'):
if 'labels' in layout:
labeltext = layout['labels'][num]
if labeltext and labeltext != "None":
label = self.get_tab_label(page)
@ -133,7 +133,7 @@ class Notebook(Container, Gtk.Notebook):
self.last_active_term[page] = make_uuid(layout['last_active_term'][num])
num = num + 1
if layout.has_key('active_page'):
if 'active_page' in layout:
# Need to do it later, or layout changes result
GObject.idle_add(self.set_current_page, int(layout['active_page']))
else:
@ -233,7 +233,7 @@ class Notebook(Container, Gtk.Notebook):
def get_children(self):
"""Return an ordered list of our children"""
children = []
for page in xrange(0,self.get_n_pages()):
for page in range(0,self.get_n_pages()):
children.append(self.get_nth_page(page))
return(children)
@ -278,13 +278,13 @@ class Notebook(Container, Gtk.Notebook):
handler = handler[0]
self.connect_child(widget, signal, handler, *args)
if metadata and metadata.has_key('tabnum'):
if metadata and 'tabnum' in metadata:
tabpos = metadata['tabnum']
else:
tabpos = -1
label = TabLabel(self.window.get_title(), self)
if metadata and metadata.has_key('label'):
if metadata and 'label' in metadata:
dbg('creating TabLabel with text: %s' % metadata['label'])
label.set_custom_label(metadata['label'])
label.connect('close-clicked', self.closetab)
@ -334,7 +334,7 @@ class Notebook(Container, Gtk.Notebook):
err('TabLabel::closetab: called on non-Notebook: %s' % widget)
return
for i in xrange(0, nb.get_n_pages() + 1):
for i in range(0, nb.get_n_pages() + 1):
if label == nb.get_tab_label(nb.get_nth_page(i)):
tabnum = i
break
@ -434,7 +434,7 @@ class Notebook(Container, Gtk.Notebook):
del(self)
# Find the last terminal in the new parent and give it focus
terms = parent.get_visible_terminals()
terms.keys()[-1].grab_focus()
list(terms.keys())[-1].grab_focus()
def page_num_descendant(self, widget):
"""Find the tabnum of the tab containing a widget at any level"""
@ -464,7 +464,7 @@ class Notebook(Container, Gtk.Notebook):
if self.terminator.doing_layout == True:
return
last_active_term = {}
for tabnum in xrange(0, self.get_n_pages()):
for tabnum in range(0, self.get_n_pages()):
nth_page = self.get_nth_page(tabnum)
if nth_page in self.last_active_term:
last_active_term[nth_page] = self.last_active_term[nth_page]
@ -501,7 +501,7 @@ class Notebook(Container, Gtk.Notebook):
#print "event: %s" % event
child = self.get_nth_page(self.get_current_page())
if child == None:
print "Child = None, return false"
print("Child = None, return false")
return False
event_widget = Gtk.get_event_widget(event)
@ -509,7 +509,7 @@ class Notebook(Container, Gtk.Notebook):
if event_widget == None or \
event_widget == child or \
event_widget.is_ancestor(child):
print "event_widget is wrong one, return false"
print("event_widget is wrong one, return false")
return False
# Not sure if we need these. I don't think wehave any action widgets

17
terminatorlib/optionparse.py Executable file → Normal file
View File

@ -1,6 +1,5 @@
#!/usr/bin/env python2
# Terminator.optionparse - Parse commandline options
# Copyright (C) 2006-2010 cmsj@tenshu.net
# Terminator.optionparse - Parse commandline options
# Copyright (C) 2006-2010 cmsj@tenshu.net
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -20,11 +19,11 @@ import sys
import os
from optparse import OptionParser, SUPPRESS_HELP
from util import dbg, err
import util
import config
import version
from translation import _
from .util import dbg, err
from . import util
from . import config
from . import version
from .translation import _
options = None
@ -110,7 +109,7 @@ icon for the window (by file or name)'))
parser.error('Additional unexpected arguments found: %s' % args)
if options.version:
print '%s %s' % (version.APP_NAME, version.APP_VERSION)
print('%s %s' % (version.APP_NAME, version.APP_VERSION))
sys.exit(0)
if options.debug_classes or options.debug_methods:

19
terminatorlib/paned.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only
"""paned.py - a base Paned container class and the vertical/horizontal
@ -7,10 +6,10 @@ variants"""
import time
from gi.repository import GObject, Gtk, Gdk
from util import dbg, err, enumerate_descendants
from terminator import Terminator
from factory import Factory
from container import Container
from .util import dbg, err, enumerate_descendants
from .terminator import Terminator
from .factory import Factory
from .container import Container
# pylint: disable-msg=R0921
# pylint: disable-msg=E1101
@ -123,7 +122,7 @@ class Paned(Container):
self.connect_child(widget, signal, handler, *args)
if metadata and \
metadata.has_key('had_focus') and \
'had_focus' in metadata and \
metadata['had_focus'] == True:
widget.grab_focus()
@ -357,7 +356,7 @@ class Paned(Container):
def create_layout(self, layout):
"""Apply layout configuration"""
if not layout.has_key('children'):
if 'children' not in layout:
err('layout specifies no children: %s' % layout)
return
@ -376,14 +375,14 @@ class Paned(Container):
for child in children:
key = children[child]['order']
child_order_map[key] = child
map_keys = child_order_map.keys()
map_keys = list(child_order_map.keys())
map_keys.sort()
for map_key in map_keys:
keys.append(child_order_map[map_key])
except KeyError:
# We've failed to figure out the order. At least give the terminals
# in the wrong order
keys = children.keys()
keys = list(children.keys())
num = 0
for child_key in keys:
@ -411,7 +410,7 @@ class Paned(Container):
self.get_child2().create_layout(children[keys[1]])
# Set the position with ratio. For some reason more reliable than by pos.
if layout.has_key('ratio'):
if 'ratio' in layout:
self.ratio = float(layout['ratio'])
self.set_position_by_ratio()

17
terminatorlib/plugin.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only
"""plugin.py - Base plugin system
@ -25,10 +24,10 @@
import sys
import os
import borg
from config import Config
from util import dbg, err, get_config_dir
from terminator import Terminator
from . import borg
from .config import Config
from .util import dbg, err, get_config_dir
from .terminator import Terminator
class Plugin(object):
"""Definition of our base plugin class"""
@ -95,7 +94,7 @@ class PluginRegistry(borg.Borg):
try:
module = __import__(plugin[:-3], None, None, [''])
for item in getattr(module, 'AVAILABLE'):
if item not in self.available_plugins.keys():
if item not in list(self.available_plugins.keys()):
func = getattr(module, item)
self.available_plugins[item] = func
@ -104,7 +103,7 @@ class PluginRegistry(borg.Borg):
continue
if item not in self.instances:
self.instances[item] = func()
except Exception, ex:
except Exception as ex:
err('PluginRegistry::load_plugins: Importing plugin %s \
failed: %s' % (plugin, ex))
@ -127,12 +126,12 @@ for %s' % (len(self.instances), capability))
def get_available_plugins(self):
"""Return a list of all available plugins whether they are enabled or
disabled"""
return(self.available_plugins.keys())
return(list(self.available_plugins.keys()))
def is_enabled(self, plugin):
"""Return a boolean value indicating whether a plugin is enabled or
not"""
return(self.instances.has_key(plugin))
return(plugin in self.instances)
def enable(self, plugin):
"""Enable a plugin"""

9
terminatorlib/plugins/activitywatch.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only
"""activitywatch.py - Terminator Plugin to watch a terminal for activity"""
@ -53,7 +52,7 @@ class ActivityWatch(plugin.MenuItem):
def callback(self, menuitems, menu, terminal):
"""Add our menu item to the menu"""
item = Gtk.CheckMenuItem.new_with_mnemonic(_('Watch for _activity'))
item.set_active(self.watches.has_key(terminal))
item.set_active(terminal in self.watches)
if item.get_active():
item.connect("activate", self.unwatch, terminal)
else:
@ -85,7 +84,7 @@ class ActivityWatch(plugin.MenuItem):
terminal.get_window_title(), 'terminator')
this_time = time.mktime(time.gmtime())
if not self.last_notifies.has_key(terminal):
if terminal not in self.last_notifies:
show_notify = True
else:
last_time = self.last_notifies[terminal]
@ -119,7 +118,7 @@ class InactivityWatch(plugin.MenuItem):
def callback(self, menuitems, menu, terminal):
"""Add our menu item to the menu"""
item = Gtk.CheckMenuItem.new_with_mnemonic(_("Watch for _silence"))
item.set_active(self.watches.has_key(terminal))
item.set_active(terminal in self.watches)
if item.get_active():
item.connect("activate", self.unwatch, terminal)
else:
@ -153,7 +152,7 @@ class InactivityWatch(plugin.MenuItem):
def check_times(self, terminal):
"""Check if this terminal has gone silent"""
time_now = time.mktime(time.gmtime())
if not self.last_activities.has_key(terminal):
if terminal not in self.last_activities:
dbg('Terminal %s has no last activity' % terminal)
return True

11
terminatorlib/plugins/custom_commands.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only
"""custom_commands.py - Terminator Plugin to add custom command menu entries"""
@ -16,7 +15,7 @@ from terminatorlib.config import Config
from terminatorlib.translation import _
from terminatorlib.util import get_config_dir, err, dbg, gerr
(CC_COL_ENABLED, CC_COL_NAME, CC_COL_COMMAND) = range(0,3)
(CC_COL_ENABLED, CC_COL_NAME, CC_COL_COMMAND) = list(range(0,3))
# Every plugin you want Terminator to load *must* be listed in 'AVAILABLE'
AVAILABLE = ['CustomCommandsMenu']
@ -35,13 +34,13 @@ class CustomCommandsMenu(plugin.MenuItem):
noord_cmds = []
for part in sections:
s = sections[part]
if not (s.has_key("name") and s.has_key("command")):
print "CustomCommandsMenu: Ignoring section %s" % s
if not ("name" in s and "command" in s):
print("CustomCommandsMenu: Ignoring section %s" % s)
continue
name = s["name"]
command = s["command"]
enabled = s["enabled"] and s["enabled"] or False
if s.has_key("position"):
if "position" in s:
self.cmd_list[int(s["position"])] = {'enabled' : enabled,
'name' : name,
'command' : command
@ -127,7 +126,7 @@ class CustomCommandsMenu(plugin.MenuItem):
if command[-1] != '\n':
command = command + '\n'
for terminal in data['terminals']:
terminal.vte.feed_child(command, len(command))
terminal.vte.feed_child_binary(command.encode(terminal.vte.get_encoding()))
def configure(self, widget, data = None):
ui = {}

View File

@ -1,5 +1,3 @@
#!/usr/bin/env python2
# Plugin by Sinan Nalkaya <sardok@gmail.com>
# See LICENSE of Terminator package.
@ -30,7 +28,7 @@ class Logger(plugin.MenuItem):
def callback(self, menuitems, menu, terminal):
""" Add save menu item to the menu"""
vte_terminal = terminal.get_vte()
if not self.loggers.has_key(vte_terminal):
if vte_terminal not in self.loggers:
item = Gtk.MenuItem.new_with_mnemonic(_('Start _Logger'))
item.connect("activate", self.start_logger, terminal)
else:

2
terminatorlib/plugins/maven.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Copyright (c) 2010 Julien Nicoulaud <julien.nicoulaud@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
@ -14,6 +13,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor
# , Boston, MA 02110-1301 USA
import re
import terminatorlib.plugin as plugin

1
terminatorlib/plugins/terminalshot.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only
"""terminalshot.py - Terminator Plugin to take 'screenshots' of individual

View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
import terminatorlib.plugin as plugin
# AVAILABLE must contain a list of all the classes that you want exposed

View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net?
# GPL v2 only
"""url_handlers.py - Default plugins for URL handling"""

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python
"""Preferences Editor for Terminator.
Load a UIBuilder config file, display it,
@ -10,14 +10,14 @@ write it to a config file
import os
from gi.repository import GObject, Gtk, Gdk
from util import dbg, err
import config
from keybindings import Keybindings, KeymapError
from translation import _
from encoding import TerminatorEncoding
from terminator import Terminator
from plugin import PluginRegistry
from version import APP_NAME
from .util import dbg, err
from . import config
from .keybindings import Keybindings, KeymapError
from .translation import _
from .encoding import TerminatorEncoding
from .terminator import Terminator
from .plugin import PluginRegistry
from .version import APP_NAME
def color2hex(widget):
"""Pull the colour values out of a Gtk ColorPicker widget and return them
@ -184,9 +184,9 @@ class PrefsEditor:
librarypath = os.path.join(head, 'preferences.glade')
gladefile = open(librarypath, 'r')
gladedata = gladefile.read()
except Exception, ex:
print "Failed to find preferences.glade"
print ex
except Exception as ex:
print("Failed to find preferences.glade")
print(ex)
return
self.builder.add_from_string(gladedata)
@ -207,7 +207,7 @@ class PrefsEditor:
try:
self.config.inhibit_save()
self.set_values()
except Exception, e:
except Exception as e:
err('Unable to set values: %s' % e)
self.config.uninhibit_save()
@ -564,7 +564,7 @@ class PrefsEditor:
# NOTE: The palette selector is set after the colour pickers
# Palette colour pickers
colourpalette = self.config['palette'].split(':')
for i in xrange(1, 17):
for i in range(1, 17):
widget = guiget('palette_colorpicker_%d' % i)
widget.set_color(Gdk.color_parse(colourpalette[i - 1]))
# Now set the palette selector widget
@ -652,7 +652,7 @@ class PrefsEditor:
encodingstore = guiget('EncodingListStore')
value = self.config['encoding']
encodings = TerminatorEncoding().get_list()
encodings.sort(lambda x, y: cmp(x[2].lower(), y[2].lower()))
encodings.sort(key=lambda x: x[2].lower())
for encoding in encodings:
if encoding[1] is None:
@ -890,7 +890,7 @@ class PrefsEditor:
guiget = self.builder.get_object
active = widget.get_active()
for key in self.palettevalues.keys():
for key in list(self.palettevalues.keys()):
if self.palettevalues[key] == active:
value = key
@ -899,20 +899,20 @@ class PrefsEditor:
else:
sensitive = False
for num in xrange(1, 17):
for num in range(1, 17):
picker = guiget('palette_colorpicker_%d' % num)
picker.set_sensitive(sensitive)
if value in self.palettes:
palette = self.palettes[value]
palettebits = palette.split(':')
for num in xrange(1, 17):
for num in range(1, 17):
# Update the visible elements
picker = guiget('palette_colorpicker_%d' % num)
picker.set_color(Gdk.color_parse(palettebits[num - 1]))
elif value == 'custom':
palettebits = []
for num in xrange(1, 17):
for num in range(1, 17):
picker = guiget('palette_colorpicker_%d' % num)
palettebits.append(color2hex(picker))
palette = ':'.join(palettebits)
@ -940,7 +940,7 @@ class PrefsEditor:
guiget = self.builder.get_object
# FIXME: We do this at least once elsewhere. refactor!
for num in xrange(1, 17):
for num in range(1, 17):
picker = guiget('palette_colorpicker_%d' % num)
value = color2hex(picker)
palettebits.append(value)
@ -1449,7 +1449,7 @@ class PrefsEditor:
guiget = self.builder.get_object
active = widget.get_active()
for key in self.colorschemevalues.keys():
for key in list(self.colorschemevalues.keys()):
if self.colorschemevalues[key] == active:
value = key
@ -1554,7 +1554,7 @@ class LayoutEditor:
listitems = {}
store.clear()
children = layout.keys()
children = list(layout.keys())
i = 0
while children != []:
child = children.pop()
@ -1650,17 +1650,17 @@ class LayoutEditor:
command.set_sensitive(True)
chooser.set_sensitive(True)
workdir.set_sensitive(True)
if layout_item.has_key('command') and layout_item['command'] != '':
if 'command' in layout_item and layout_item['command'] != '':
command.set_text(layout_item['command'])
else:
command.set_text('')
if layout_item.has_key('profile') and layout_item['profile'] != '':
if 'profile' in layout_item and layout_item['profile'] != '':
chooser.set_active(self.profile_profile_to_ids[layout_item['profile']])
else:
chooser.set_active(0)
if layout_item.has_key('directory') and layout_item['directory'] != '':
if 'directory' in layout_item and layout_item['directory'] != '':
workdir.set_text(layout_item['directory'])
else:
workdir.set_text('')
@ -1689,9 +1689,9 @@ class LayoutEditor:
self.config.save()
if __name__ == '__main__':
import util
from . import util
util.DEBUG = True
import terminal
from . import terminal
TERM = terminal.Terminal()
PREFEDIT = PrefsEditor(TERM)

0
terminatorlib/pylint.sh Executable file → Normal file
View File

5
terminatorlib/searchbar.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only
"""searchbar.py - classes necessary to provide a terminal search bar"""
@ -7,8 +6,8 @@ from gi.repository import Gtk, Gdk
from gi.repository import GObject
from gi.repository import GLib
from translation import _
from config import Config
from .translation import _
from .config import Config
# pylint: disable-msg=R0904
class Searchbar(Gtk.HBox):

21
terminatorlib/signalman.py Executable file → Normal file
View File

@ -1,9 +1,8 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only
"""Simple management of Gtk Widget signal handlers"""
from util import dbg, err
from .util import dbg, err
class Signalman(object):
"""Class providing glib signal tracking and management"""
@ -16,16 +15,16 @@ class Signalman(object):
def __del__(self):
"""Class destructor. This is only used to check for stray signals"""
if len(self.cnxids.keys()) > 0:
if len(list(self.cnxids.keys())) > 0:
dbg('Remaining signals: %s' % self.cnxids)
def new(self, widget, signal, handler, *args):
"""Register a new signal on a widget"""
if not self.cnxids.has_key(widget):
if widget not in self.cnxids:
dbg('creating new bucket for %s' % type(widget))
self.cnxids[widget] = {}
if self.cnxids[widget].has_key(signal):
if signal in self.cnxids[widget]:
err('%s already has a handler for %s' % (id(widget), signal))
self.cnxids[widget][signal] = widget.connect(signal, handler, *args)
@ -34,31 +33,31 @@ class Signalman(object):
def remove_signal(self, widget, signal):
"""Remove a signal handler"""
if not self.cnxids.has_key(widget):
if widget not in self.cnxids:
dbg('%s is not registered' % widget)
return
if not self.cnxids[widget].has_key(signal):
if signal not in self.cnxids[widget]:
dbg('%s not registered for %s' % (signal, type(widget)))
return
dbg('removing %s::%s' % (type(widget), signal))
widget.disconnect(self.cnxids[widget][signal])
del(self.cnxids[widget][signal])
if len(self.cnxids[widget].keys()) == 0:
if len(list(self.cnxids[widget].keys())) == 0:
dbg('no more signals for widget')
del(self.cnxids[widget])
def remove_widget(self, widget):
"""Remove all signal handlers for a widget"""
if not self.cnxids.has_key(widget):
if widget not in self.cnxids:
dbg('%s not registered' % widget)
return
signals = self.cnxids[widget].keys()
signals = list(self.cnxids[widget].keys())
for signal in signals:
self.remove_signal(widget, signal)
def remove_all(self):
"""Remove all signal handlers for all widgets"""
widgets = self.cnxids.keys()
widgets = list(self.cnxids.keys())
for widget in widgets:
self.remove_widget(widget)

117
terminatorlib/terminal.py Executable file → Normal file
View File

@ -1,9 +1,8 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only
"""terminal.py - classes necessary to provide Terminal widgets"""
from __future__ import division
import os
import signal
import gi
@ -11,22 +10,27 @@ from gi.repository import GLib, GObject, Pango, Gtk, Gdk
gi.require_version('Vte', '2.91') # vte-0.38 (gnome-3.14)
from gi.repository import Vte
import subprocess
import urllib
import urllib.request, urllib.parse, urllib.error
from util import dbg, err, spawn_new_terminator, make_uuid, manual_lookup, display_manager
import util
from config import Config
from cwd import get_default_cwd
from factory import Factory
from terminator import Terminator
from titlebar import Titlebar
from terminal_popup_menu import TerminalPopupMenu
from searchbar import Searchbar
from translation import _
from signalman import Signalman
import plugin
from .util import dbg, err, spawn_new_terminator, make_uuid, manual_lookup, display_manager
from . import util
from .config import Config
from .cwd import get_default_cwd
from .factory import Factory
from .terminator import Terminator
from .titlebar import Titlebar
from .terminal_popup_menu import TerminalPopupMenu
from .searchbar import Searchbar
from .translation import _
from .signalman import Signalman
from . import plugin
from terminatorlib.layoutlauncher import LayoutLauncher
# constant for vte matching
# TODO: Please replace with a proper reference to VTE, I found none!
PCRE2_MULTILINE = 0x00000400
# pylint: disable-msg=R0904
class Terminal(Gtk.VBox):
"""Class implementing the VTE widget and its wrappings"""
@ -143,8 +147,7 @@ class Terminal(Gtk.VBox):
self.vte.show()
self.default_encoding = self.vte.get_encoding()
self.regex_flags = (GLib.RegexCompileFlags.OPTIMIZE | \
GLib.RegexCompileFlags.MULTILINE)
self.regex_flags = (Vte.REGEX_FLAGS_DEFAULT | PCRE2_MULTILINE)
self.update_url_matches()
self.terminalbox = self.create_terminalbox()
@ -232,7 +235,7 @@ class Terminal(Gtk.VBox):
try:
dbg('close: killing %d' % self.pid)
os.kill(self.pid, signal.SIGHUP)
except Exception, ex:
except Exception as ex:
# We really don't want to care if this failed. Deep OS voodoo is
# not what we should be doing.
dbg('os.kill failed: %s' % ex)
@ -255,6 +258,11 @@ class Terminal(Gtk.VBox):
return(terminalbox)
def _add_regex(self, name, re):
reg = Vte.Regex.new_for_match(re, len(re), self.regex_flags)
self.matches[name] = self.vte.match_add_regex(reg, 0)
self.vte.match_set_cursor_name(self.matches[name], 'pointer')
def update_url_matches(self):
"""Update the regexps used to match URLs"""
userchars = "-A-Za-z0-9"
@ -271,34 +279,32 @@ class Terminal(Gtk.VBox):
re = (lboundry + schemes +
"//(" + user + "@)?[" + hostchars +".]+(:[0-9]+)?(" +
urlpath + ")?" + rboundry + "/?")
reg = GLib.Regex.new(re, self.regex_flags, 0)
self.matches['full_uri'] = self.vte.match_add_gregex(reg, 0)
self._add_regex('full_uri', re)
if self.matches['full_uri'] == -1:
err ('Terminal::update_url_matches: Failed adding URL matches')
else:
re = (lboundry +
'(callto:|h323:|sip:)' + "[" + userchars + "+][" +
userchars + ".]*(:[0-9]+)?@?[" + pathchars + "]+" +
'(callto:|h323:|sip:)' + "[" + userchars + "+][" +
userchars + ".]*(:[0-9]+)?@?[" + pathchars + "]+" +
rboundry)
reg = GLib.Regex.new(re, self.regex_flags, 0)
self.matches['voip'] = self.vte.match_add_gregex(reg, 0)
self._add_regex('voip', re)
re = (lboundry +
"(www|ftp)[" + hostchars + "]*\.[" + hostchars +
"(www|ftp)[" + hostchars + "]*\.[" + hostchars +
".]+(:[0-9]+)?(" + urlpath + ")?" + rboundry + "/?")
reg = GLib.Regex.new(re, self.regex_flags, 0)
self.matches['addr_only'] = self.vte.match_add_gregex(reg, 0)
self._add_regex('addr_only', re)
re = (lboundry +
"(mailto:)?[a-zA-Z0-9][a-zA-Z0-9.+-]*@[a-zA-Z0-9]" +
"[a-zA-Z0-9-]*\.[a-zA-Z0-9][a-zA-Z0-9-]+" +
"[.a-zA-Z0-9-]*" + rboundry)
reg = GLib.Regex.new(re, self.regex_flags, 0)
self.matches['email'] = self.vte.match_add_gregex(reg, 0)
self._add_regex('email', re)
re = (lboundry +
"""news:[-A-Z\^_a-z{|}~!"#$%&'()*+,./0-9;:=?`]+@""" +
"[-A-Za-z0-9.]+(:[0-9]+)?" + rboundry)
reg = GLib.Regex.new(re, self.regex_flags, 0)
self.matches['nntp'] = self.vte.match_add_gregex(reg, 0)
self._add_regex('nntp', re)
# Now add any matches from plugins
try:
@ -312,12 +318,13 @@ class Terminal(Gtk.VBox):
if name in self.matches:
dbg('refusing to add duplicate match %s' % name)
continue
reg = GLib.Regex.new(match, self.regex_flags, 0)
self.matches[name] = self.vte.match_add_gregex(reg, 0)
dbg('added plugin URL handler for %s (%s) as %d' %
self._add_regex(name, match)
dbg('added plugin URL handler for %s (%s) as %d' %
(name, urlplugin.__class__.__name__,
self.matches[name]))
except Exception, ex:
except Exception as ex:
err('Exception occurred adding plugin URL match: %s' % ex)
def match_add(self, name, match):
@ -325,8 +332,8 @@ class Terminal(Gtk.VBox):
if name in self.matches:
err('Terminal::match_add: Refusing to create duplicate match %s' % name)
return
reg = GLib.Regex.new(match, self.regex_flags, 0)
self.matches[name] = self.vte.match_add_gregex(reg, 0)
self._add_regex(name, match)
def match_remove(self, name):
"""Remove a previously registered URL match"""
@ -495,9 +502,9 @@ class Terminal(Gtk.VBox):
groupitems = []
cnxs = []
for key, value in {_('Broadcast _all'):'all',
for key, value in list({_('Broadcast _all'):'all',
_('Broadcast _group'):'group',
_('Broadcast _off'):'off'}.items():
_('Broadcast _off'):'off'}.items()):
item = Gtk.RadioMenuItem.new_with_mnemonic(groupitems, key)
groupitems = item.get_group()
dbg('Terminal::populate_group_menu: %s active: %s' %
@ -588,7 +595,7 @@ class Terminal(Gtk.VBox):
def set_groupsend(self, _widget, value):
"""Set the groupsend mode"""
# FIXME: Can we think of a smarter way of doing this than poking?
if value in self.terminator.groupsend_type.values():
if value in list(self.terminator.groupsend_type.values()):
dbg('Terminal::set_groupsend: setting groupsend to %s' % value)
self.terminator.groupsend = value
@ -714,15 +721,15 @@ class Terminal(Gtk.VBox):
if len(colors) == 16:
# RGB values for indices 16..255 copied from vte source in order to dim them
shades = [0, 95, 135, 175, 215, 255]
for r in xrange(0, 6):
for g in xrange(0, 6):
for b in xrange(0, 6):
for r in range(0, 6):
for g in range(0, 6):
for b in range(0, 6):
newcolor = Gdk.RGBA()
setattr(newcolor, "red", shades[r] / 255.0)
setattr(newcolor, "green", shades[g] / 255.0)
setattr(newcolor, "blue", shades[b] / 255.0)
self.palette_active.append(newcolor)
for y in xrange(8, 248, 10):
for y in range(8, 248, 10):
newcolor = Gdk.RGBA()
setattr(newcolor, "red", y / 255.0)
setattr(newcolor, "green", y / 255.0)
@ -743,7 +750,7 @@ class Terminal(Gtk.VBox):
self.palette_inactive)
profiles = self.config.base.profiles
terminal_box_style_context = self.terminalbox.get_style_context()
for profile in profiles.keys():
for profile in list(profiles.keys()):
munged_profile = "terminator-profile-%s" % (
"".join([c if c.isalnum() else "-" for c in profile]))
if terminal_box_style_context.has_class(munged_profile):
@ -1016,7 +1023,7 @@ class Terminal(Gtk.VBox):
_time, data):
"""I have no idea what this does, drag and drop is a mystery. sorry."""
selection_data.set(Gdk.atom_intern('vte', False), info,
str(data.terminator.terminals.index(self)))
bytes(str(data.terminator.terminals.index(self)), 'utf-8'))
def on_drag_motion(self, widget, drag_context, x, y, _time, _data):
"""*shrug*"""
@ -1113,7 +1120,7 @@ class Terminal(Gtk.VBox):
str=''
for fname in txt_lines[:-1]:
dbg('drag data fname: %s' % fname)
fname = "'%s'" % urllib.unquote(fname[7:].replace("'",
fname = "'%s'" % urllib.parse.unquote(fname[7:].replace("'",
'\'\\\'\''))
str += fname + ' '
txt=str
@ -1453,7 +1460,7 @@ class Terminal(Gtk.VBox):
url = 'ftp://' + url
elif match == self.matches['addr_only']:
url = 'http://' + url
elif match in self.matches.values():
elif match in list(self.matches.values()):
# We have a match, but it's not a hard coded one, so it's a plugin
try:
registry = plugin.PluginRegistry()
@ -1468,7 +1475,7 @@ class Terminal(Gtk.VBox):
%s plugin' % urlplugin.handler_name)
url = newurl
break
except Exception, ex:
except Exception as ex:
err('Exception occurred preparing URL: %s' % ex)
return(url)
@ -1629,20 +1636,20 @@ class Terminal(Gtk.VBox):
def create_layout(self, layout):
"""Apply our layout"""
dbg('Setting layout')
if layout.has_key('command') and layout['command'] != '':
if 'command' in layout and layout['command'] != '':
self.layout_command = layout['command']
if layout.has_key('profile') and layout['profile'] != '':
if 'profile' in layout and layout['profile'] != '':
if layout['profile'] in self.config.list_profiles():
self.set_profile(self, layout['profile'])
if layout.has_key('group') and layout['group'] != '':
if 'group' in layout and layout['group'] != '':
# This doesn't need/use self.titlebar, but it's safer than sending
# None
self.really_create_group(self.titlebar, layout['group'])
if layout.has_key('title') and layout['title'] != '':
if 'title' in layout and layout['title'] != '':
self.titlebar.set_custom_string(layout['title'])
if layout.has_key('directory') and layout['directory'] != '':
if 'directory' in layout and layout['directory'] != '':
self.directory = layout['directory']
if layout.has_key('uuid') and layout['uuid'] != '':
if 'uuid' in layout and layout['uuid'] != '':
self.uuid = make_uuid(layout['uuid'])
def scroll_by_page(self, pages):

29
terminatorlib/terminal_popup_menu.py Executable file → Normal file
View File

@ -1,21 +1,18 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only
"""terminal_popup_menu.py - classes necessary to provide a terminal context
menu"""
import string
from gi.repository import Gtk
from version import APP_NAME
from translation import _
from encoding import TerminatorEncoding
from terminator import Terminator
from util import err, dbg
from config import Config
from prefseditor import PrefsEditor
import plugin
from .version import APP_NAME
from .translation import _
from .encoding import TerminatorEncoding
from .terminator import Terminator
from .util import err, dbg
from .config import Config
from .prefseditor import PrefsEditor
from . import plugin
class TerminalPopupMenu(object):
"""Class implementing the Terminal context menu"""
@ -51,7 +48,7 @@ class TerminalPopupMenu(object):
if url and url[0]:
dbg("URL matches id: %d" % url[1])
if not url[1] in terminal.matches.values():
if not url[1] in list(terminal.matches.values()):
err("Unknown URL match id: %d" % url[1])
dbg("Available matches: %s" % terminal.matches)
@ -63,7 +60,7 @@ class TerminalPopupMenu(object):
elif url[1] == terminal.matches['voip']:
nameopen = _('Ca_ll VoIP address')
namecopy = _('_Copy VoIP address')
elif url[1] in terminal.matches.values():
elif url[1] in list(terminal.matches.values()):
# This is a plugin match
for pluginname in terminal.matches:
if terminal.matches[pluginname] == url[1]:
@ -191,7 +188,7 @@ class TerminalPopupMenu(object):
item.connect('activate', lambda x: PrefsEditor(self.terminal))
menu.append(item)
profilelist = sorted(self.config.list_profiles(), key=string.lower)
profilelist = sorted(self.config.list_profiles(), key=str.lower)
if len(profilelist) > 1:
item = Gtk.MenuItem.new_with_mnemonic(_('Profiles'))
@ -228,7 +225,7 @@ class TerminalPopupMenu(object):
for menuitem in menuitems:
menu.append(menuitem)
except Exception, ex:
except Exception as ex:
err('TerminalPopupMenu::show: %s' % ex)
menu.show_all()
@ -246,7 +243,7 @@ class TerminalPopupMenu(object):
submenu = Gtk.Menu ()
item.set_submenu (submenu)
encodings = TerminatorEncoding ().get_list ()
encodings.sort (lambda x, y: cmp (x[2].lower (), y[2].lower ()))
encodings.sort (key=lambda x: x[2].lower ())
current_encoding = terminal.vte.get_encoding ()
group = None

53
terminatorlib/terminator.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only
"""terminator.py - class for the master Terminator singleton"""
@ -10,14 +9,14 @@ gi.require_version('Vte', '2.91')
from gi.repository import Gtk, Gdk, Vte, GdkX11
from gi.repository.GLib import GError
import borg
from borg import Borg
from config import Config
from keybindings import Keybindings
from util import dbg, err, enumerate_descendants
from factory import Factory
from cwd import get_pid_cwd
from version import APP_NAME, APP_VERSION
from . import borg
from .borg import Borg
from .config import Config
from .keybindings import Keybindings
from .util import dbg, err, enumerate_descendants
from .factory import Factory
from .cwd import get_pid_cwd
from .version import APP_NAME, APP_VERSION
def eventkey2gdkevent(eventkey): # FIXME FOR GTK3: is there a simpler way of casting from specific EventKey to generic (union) GdkEvent?
gdkevent = Gdk.Event.new(eventkey.type)
@ -267,34 +266,34 @@ class Terminator(Borg):
count = count + 1
if count == 1000:
err('hit maximum loop boundary. THIS IS VERY LIKELY A BUG')
for obj in layout.keys():
for obj in list(layout.keys()):
if layout[obj]['type'].lower() == 'window':
hierarchy[obj] = {}
hierarchy[obj]['type'] = 'Window'
hierarchy[obj]['children'] = {}
# Copy any additional keys
for objkey in layout[obj].keys():
if layout[obj][objkey] != '' and not hierarchy[obj].has_key(objkey):
for objkey in list(layout[obj].keys()):
if layout[obj][objkey] != '' and objkey not in hierarchy[obj]:
hierarchy[obj][objkey] = layout[obj][objkey]
objects[obj] = hierarchy[obj]
del(layout[obj])
else:
# Now examine children to see if their parents exist yet
if not layout[obj].has_key('parent'):
if 'parent' not in layout[obj]:
err('Invalid object: %s' % obj)
del(layout[obj])
continue
if objects.has_key(layout[obj]['parent']):
if layout[obj]['parent'] in objects:
# Our parent has been created, add ourselves
childobj = {}
childobj['type'] = layout[obj]['type']
childobj['children'] = {}
# Copy over any additional object keys
for objkey in layout[obj].keys():
if not childobj.has_key(objkey):
for objkey in list(layout[obj].keys()):
if objkey not in childobj:
childobj[objkey] = layout[obj][objkey]
objects[layout[obj]['parent']]['children'][obj] = childobj
@ -309,25 +308,25 @@ class Terminator(Borg):
raise(ValueError)
dbg('Creating a window')
window, terminal = self.new_window()
if layout[windef].has_key('position'):
if 'position' in layout[windef]:
parts = layout[windef]['position'].split(':')
if len(parts) == 2:
window.move(int(parts[0]), int(parts[1]))
if layout[windef].has_key('size'):
if 'size' in layout[windef]:
parts = layout[windef]['size']
winx = int(parts[0])
winy = int(parts[1])
if winx > 1 and winy > 1:
window.resize(winx, winy)
if layout[windef].has_key('title'):
if 'title' in layout[windef]:
window.title.force_title(layout[windef]['title'])
if layout[windef].has_key('maximised'):
if 'maximised' in layout[windef]:
if layout[windef]['maximised'] == 'True':
window.ismaximised = True
else:
window.ismaximised = False
window.set_maximised(window.ismaximised)
if layout[windef].has_key('fullscreen'):
if 'fullscreen' in layout[windef]:
if layout[windef]['fullscreen'] == 'True':
window.isfullscreen = True
else:
@ -359,7 +358,7 @@ class Terminator(Borg):
# For windows with a notebook
notebook = window.get_toplevel().get_children()[0]
# Cycle through pages by number
for page in xrange(0, notebook.get_n_pages()):
for page in range(0, notebook.get_n_pages()):
# Try and get the entry in the previously saved mapping
mapping = window_last_active_term_mapping[window]
page_last_active_term = mapping.get(notebook.get_nth_page(page), None)
@ -475,7 +474,7 @@ class Terminator(Borg):
background-color: alpha(%s, %s); }
"""
profiles = self.config.base.profiles
for profile in profiles.keys():
for profile in list(profiles.keys()):
if profiles[profile]['use_theme_colors']:
# Create a dummy window/vte and realise it so it has correct
# values to read from
@ -502,7 +501,7 @@ class Terminator(Borg):
css += template % (munged_profile, bgcolor, bgalpha)
style_provider = Gtk.CssProvider()
style_provider.load_from_data(css)
style_provider.load_from_data(css.encode('utf-8'))
self.style_providers.append(style_provider)
# Attempt to load some theme specific stylistic tweaks for appearances
@ -538,19 +537,19 @@ class Terminator(Borg):
# Size the GtkPaned splitter handle size.
css = ""
if self.config['handle_size'] in xrange(0, 21):
if self.config['handle_size'] in range(0, 21):
css += """
.terminator-terminal-window GtkPaned,
.terminator-terminal-window paned {
-GtkPaned-handle-size: %s; }
""" % self.config['handle_size']
style_provider = Gtk.CssProvider()
style_provider.load_from_data(css)
style_provider.load_from_data(css.encode('utf-8'))
self.style_providers.append(style_provider)
# Apply the providers, incrementing priority so they don't cancel out
# each other
for idx in xrange(0, len(self.style_providers)):
for idx in range(0, len(self.style_providers)):
Gtk.StyleContext.add_provider_for_screen(
Gdk.Screen.get_default(),
self.style_providers[idx],

11
terminatorlib/titlebar.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only
"""titlebar.py - classes necessary to provide a terminal title bar"""
@ -9,11 +8,11 @@ from gi.repository import Pango
import random
import itertools
from version import APP_NAME
from util import dbg
from terminator import Terminator
from editablelabel import EditableLabel
from translation import _
from .version import APP_NAME
from .util import dbg
from .terminator import Terminator
from .editablelabel import EditableLabel
from .translation import _
# pylint: disable-msg=R0904
# pylint: disable-msg=W0613

View File

@ -1,6 +1,5 @@
#!/usr/bin/env python2
# Terminator - multiple gnome terminals in one window
# Copyright (C) 2006-2010 cmsj@tenshu.net
# Terminator - multiple gnome terminals in one window
# Copyright (C) 2006-2010 cmsj@tenshu.net
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -17,8 +16,8 @@
"""Terminator by Chris Jones <cmsj@tenshu.net>"""
from version import APP_NAME
from util import dbg
from .version import APP_NAME
from .util import dbg
_ = None

11
terminatorlib/util.py Executable file → Normal file
View File

@ -1,6 +1,5 @@
#!/usr/bin/env python2
# Terminator.util - misc utility functions
# Copyright (C) 2006-2010 cmsj@tenshu.net
# Terminator.util - misc utility functions
# Copyright (C) 2006-2010 cmsj@tenshu.net
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -64,14 +63,14 @@ def dbg(log = ""):
if DEBUGMETHODS != [] and method not in DEBUGMETHODS:
return
try:
print >> sys.stderr, "%s::%s: %s%s" % (classname, method, log, extra)
print("%s::%s: %s%s" % (classname, method, log, extra), file=sys.stderr)
except IOError:
pass
def err(log = ""):
"""Print an error message"""
try:
print >> sys.stderr, log
print(log, file=sys.stderr)
except IOError:
pass
@ -279,7 +278,7 @@ def enumerate_descendants(parent):
terminals"""
# FIXME: Does having to import this here mean we should move this function
# back to Container?
from factory import Factory
from .factory import Factory
containerstmp = []
containers = []

View File

@ -1,6 +1,5 @@
#!/usr/bin/env python2
# TerminatorVersion - version number
# Copyright (C) 2010 cmsj@tenshu.net
# TerminatorVersion - version number
# Copyright (C) 2010 cmsj@tenshu.net
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

27
terminatorlib/window.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only
"""window.py - class for the main Terminator window"""
@ -10,13 +9,13 @@ import gi
from gi.repository import GObject
from gi.repository import Gtk, Gdk, GdkX11
from util import dbg, err, make_uuid, display_manager
import util
from translation import _
from version import APP_NAME
from container import Container
from factory import Factory
from terminator import Terminator
from .util import dbg, err, make_uuid, display_manager
from . import util
from .translation import _
from .version import APP_NAME
from .container import Container
from .factory import Factory
from .terminator import Terminator
if display_manager() == 'X11':
try:
@ -837,9 +836,9 @@ class Window(Container, Gtk.Window):
for term in possibles:
rect = layout[term]
offsets[term] = util.get_nav_offset(edge, rect, direction)
keys = offsets.values()
keys = list(offsets.values())
keys.sort()
winners = [k for k, v in offsets.iteritems() if v == keys[0]]
winners = [k for k, v in offsets.items() if v == keys[0]]
next = terminals.index(winners[0])
if len(winners) > 1:
@ -862,7 +861,7 @@ class Window(Container, Gtk.Window):
def create_layout(self, layout):
"""Apply any config items from our layout"""
if not layout.has_key('children'):
if 'children' not in layout:
err('layout describes no children: %s' % layout)
return
children = layout['children']
@ -871,7 +870,7 @@ class Window(Container, Gtk.Window):
err('incorrect number of children for Window: %s' % layout)
return
child = children[children.keys()[0]]
child = children[list(children.keys())[0]]
terminal = self.get_children()[0]
dbg('Making a child of type: %s' % child['type'])
if child['type'] == 'VPaned':
@ -892,10 +891,10 @@ class Window(Container, Gtk.Window):
self.get_children()[0].create_layout(child)
if layout.has_key('last_active_term') and layout['last_active_term'] not in ['', None]:
if 'last_active_term' in layout and layout['last_active_term'] not in ['', None]:
self.last_active_term = make_uuid(layout['last_active_term'])
if layout.has_key('last_active_window') and layout['last_active_window'] == 'True':
if 'last_active_window' in layout and layout['last_active_window'] == 'True':
self.terminator.last_active_window = self.uuid
class WindowTitle(object):

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python
"""Load up the tests."""
import os

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python
# Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only
"""testborg.py - We are the borg. Resistance is futile.
@ -57,3 +57,4 @@ class TestBorg2(Borg):
if not self.attribute:
self.attribute = 1
# TODO: implement test?

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python
# Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only
"""testsignalman.py - Test the signalman class
@ -53,11 +53,11 @@ class TestWidget():
del(self.signals[signalid])
def handler():
print "I am a test handler"
print("I am a test handler")
if __name__ == '__main__':
import sys
import doctest
(failed, attempted) = doctest.testmod()
print "%d/%d tests failed" % (failed, attempted)
print("%d/%d tests failed" % (failed, attempted))
sys.exit(failed)