[pitivi/ges: 159/287] utils: Add logging functions/classes in pitivi/utils
- From: Jean-FranÃois Fortin Tam <jfft src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pitivi/ges: 159/287] utils: Add logging functions/classes in pitivi/utils
- Date: Thu, 15 Mar 2012 16:39:11 +0000 (UTC)
commit 28fa6240f9be8838bf79363bc2df6bef26730caf
Author: Thibault Saunier <thibault saunier collabora com>
Date: Mon Jan 9 13:22:20 2012 -0300
utils: Add logging functions/classes in pitivi/utils
No reason to have a special folder for it.
configure.ac | 1 -
pitivi/Makefile.am | 3 +-
pitivi/application.py | 4 +-
pitivi/encode.py | 2 +-
pitivi/log/Makefile.am | 11 --
pitivi/log/loggable.py | 43 -----
pitivi/log/termcolor.py | 213 ----------------------
pitivi/log/test_log.py | 284 -----------------------------
pitivi/project.py | 2 +-
pitivi/projectmanager.py | 2 +-
pitivi/settings.py | 2 +-
pitivi/sourcelist.py | 2 +-
pitivi/system.py | 2 +-
pitivi/threads.py | 2 +-
pitivi/ui/clipproperties.py | 2 +-
pitivi/ui/common.py | 2 +-
pitivi/ui/controller.py | 2 +-
pitivi/ui/effectlist.py | 2 +-
pitivi/ui/encodingdialog.py | 2 +-
pitivi/ui/filechooserpreview.py | 2 +-
pitivi/ui/filelisterrordialog.py | 2 +-
pitivi/ui/gstwidget.py | 2 +-
pitivi/ui/mainwindow.py | 2 +-
pitivi/ui/previewer.py | 2 +-
pitivi/ui/ruler.py | 2 +-
pitivi/ui/sourcelist.py | 2 +-
pitivi/ui/timeline.py | 2 +-
pitivi/ui/timelinecanvas.py | 2 +-
pitivi/ui/timelinecontrols.py | 2 +-
pitivi/ui/track.py | 2 +-
pitivi/ui/trackobject.py | 2 +-
pitivi/ui/viewer.py | 2 +-
pitivi/undo/undo.py | 2 +-
pitivi/utils/Makefile.am | 1 +
pitivi/utils/align.py | 2 +-
pitivi/utils/extract.py | 2 +-
pitivi/{log/log.py => utils/loggable.py} | 264 +++++++++++++++++++++++++--
pitivi/utils/misc.py | 2 +-
pitivi/utils/timeline.py | 2 +-
tests/Makefile.am | 1 +
tests/runtests.py | 2 +-
tests/test_log.py | 288 ++++++++++++++++++++++++++++++
42 files changed, 569 insertions(+), 606 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 09a1e42..81fa597 100644
--- a/configure.ac
+++ b/configure.ac
@@ -87,7 +87,6 @@ help/Makefile
pitivi/Makefile
pitivi/configure.py
pitivi/ui/Makefile
-pitivi/log/Makefile
pitivi/undo/Makefile
pitivi/utils/Makefile
pitivi.spec
diff --git a/pitivi/Makefile.am b/pitivi/Makefile.am
index a4b93a1..1f144b5 100644
--- a/pitivi/Makefile.am
+++ b/pitivi/Makefile.am
@@ -1,8 +1,7 @@
SUBDIRS = \
ui \
utils \
- undo \
- log
+ undo
pitividir = $(libdir)/pitivi/python/pitivi
diff --git a/pitivi/application.py b/pitivi/application.py
index 34cc562..270c47c 100644
--- a/pitivi/application.py
+++ b/pitivi/application.py
@@ -43,8 +43,8 @@ from pitivi.settings import GlobalSettings
from pitivi.threads import ThreadMaster
from pitivi.signalinterface import Signallable
from pitivi.system import getSystem
-from pitivi.log.loggable import Loggable
-from pitivi.log import log
+from pitivi.utils.loggable import Loggable
+import pitivi.utils.loggable as log
from pitivi.ui.mainwindow import PitiviMainWindow
from pitivi.projectmanager import ProjectManager, ProjectLogObserver
from pitivi.undo.undo import UndoableActionLog, DebugActionLogObserver
diff --git a/pitivi/encode.py b/pitivi/encode.py
index 06f7eec..a008817 100644
--- a/pitivi/encode.py
+++ b/pitivi/encode.py
@@ -25,7 +25,7 @@ Encoding-related utilities and classes
import gst
-import pitivi.log.log as log
+import pitivi.utils.loggable as log
def get_compatible_sink_pad(factoryname, caps):
diff --git a/pitivi/project.py b/pitivi/project.py
index 22bd4d3..ad8d0ab 100644
--- a/pitivi/project.py
+++ b/pitivi/project.py
@@ -27,7 +27,7 @@ import ges
import gst
from pitivi.utils.misc import Seeker
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
from pitivi.sourcelist import SourceList
from pitivi.settings import MultimediaSettings
from pitivi.signalinterface import Signallable
diff --git a/pitivi/projectmanager.py b/pitivi/projectmanager.py
index c7bfb3d..21a50f2 100644
--- a/pitivi/projectmanager.py
+++ b/pitivi/projectmanager.py
@@ -30,7 +30,7 @@ from pwd import getpwuid
from pitivi.project import Project
from pitivi.signalinterface import Signallable
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
from pitivi.undo.undo import UndoableAction
diff --git a/pitivi/settings.py b/pitivi/settings.py
index 3c6488c..f0bdf7b 100644
--- a/pitivi/settings.py
+++ b/pitivi/settings.py
@@ -33,7 +33,7 @@ from gettext import gettext as _
from pitivi.signalinterface import Signallable
from pitivi.encode import available_combinations, \
get_compatible_sink_caps
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
def get_bool_env(var):
diff --git a/pitivi/sourcelist.py b/pitivi/sourcelist.py
index b484627..5108a63 100644
--- a/pitivi/sourcelist.py
+++ b/pitivi/sourcelist.py
@@ -28,7 +28,7 @@ import urllib
import gst
from pitivi.signalinterface import Signallable
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
class SourceListError(Exception):
diff --git a/pitivi/system.py b/pitivi/system.py
index 3f002a5..881182a 100644
--- a/pitivi/system.py
+++ b/pitivi/system.py
@@ -23,7 +23,7 @@
import os
from pitivi.configure import APPNAME
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
from pitivi.signalinterface import Signallable
diff --git a/pitivi/threads.py b/pitivi/threads.py
index f274faa..e4724a0 100644
--- a/pitivi/threads.py
+++ b/pitivi/threads.py
@@ -24,7 +24,7 @@ Threading support
import threading
from pitivi.signalinterface import Signallable
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
#
# Following code was freely adapted by code from:
diff --git a/pitivi/ui/clipproperties.py b/pitivi/ui/clipproperties.py
index 04a2872..038e7b3 100644
--- a/pitivi/ui/clipproperties.py
+++ b/pitivi/ui/clipproperties.py
@@ -33,7 +33,7 @@ from gettext import gettext as _
from pitivi.utils.misc import Seeker
from pitivi.check import soft_deps
from pitivi.configure import get_ui_dir
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
from pitivi.effects import AUDIO_EFFECT, VIDEO_EFFECT
diff --git a/pitivi/ui/common.py b/pitivi/ui/common.py
index 40628f2..d3a314c 100644
--- a/pitivi/ui/common.py
+++ b/pitivi/ui/common.py
@@ -11,7 +11,7 @@ from gettext import ngettext
from gettext import gettext as _
from pitivi.settings import GlobalSettings
-from pitivi.log.log import doLog, ERROR
+from pitivi.utils.loggable import doLog, ERROR
GlobalSettings.addConfigSection("user-interface")
LAYER_HEIGHT_EXPANDED = 50
diff --git a/pitivi/ui/controller.py b/pitivi/ui/controller.py
index e6b4b15..e28a09d 100644
--- a/pitivi/ui/controller.py
+++ b/pitivi/ui/controller.py
@@ -22,7 +22,7 @@
import gtk.gdk
from pitivi.ui.point import Point
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
from pitivi.receiver import receiver, handler
# Controllers are reusable and implement specific behaviors. Currently this
diff --git a/pitivi/ui/effectlist.py b/pitivi/ui/effectlist.py
index cfa3f71..338064c 100644
--- a/pitivi/ui/effectlist.py
+++ b/pitivi/ui/effectlist.py
@@ -32,7 +32,7 @@ import pitivi.ui.dnd as dnd
from pitivi.configure import get_pixmap_dir
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
from pitivi.effects import AUDIO_EFFECT, VIDEO_EFFECT
from pitivi.ui.common import SPACING
from pitivi.settings import GlobalSettings
diff --git a/pitivi/ui/encodingdialog.py b/pitivi/ui/encodingdialog.py
index ef42c59..a4edcb5 100644
--- a/pitivi/ui/encodingdialog.py
+++ b/pitivi/ui/encodingdialog.py
@@ -37,7 +37,7 @@ from pitivi.utils.misc import togglePlayback, Seeker, beautify_ETA
from pitivi.settings import MultimediaSettings
from pitivi.signalinterface import Signallable
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
from pitivi.ui.gstwidget import GstElementSettingsDialog
from pitivi.ui.ripple_update_group import RippleUpdateGroup
from pitivi.ui.common import model, frame_rates, audio_rates, audio_depths, \
diff --git a/pitivi/ui/filechooserpreview.py b/pitivi/ui/filechooserpreview.py
index 7b1f69b..38e9b3c 100644
--- a/pitivi/ui/filechooserpreview.py
+++ b/pitivi/ui/filechooserpreview.py
@@ -5,7 +5,7 @@ import gtk
import pango
import os
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
from pitivi.ui.common import beautify_stream
from pitivi.utils.misc import beautify_length, uri_is_valid
from pitivi.configure import get_pixmap_dir
diff --git a/pitivi/ui/filelisterrordialog.py b/pitivi/ui/filelisterrordialog.py
index 14d90f4..ff7e8ce 100644
--- a/pitivi/ui/filelisterrordialog.py
+++ b/pitivi/ui/filelisterrordialog.py
@@ -32,7 +32,7 @@ from gettext import gettext as _
from urllib import unquote
from pitivi.configure import get_ui_dir
from pitivi.signalinterface import Signallable
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
class FileListErrorDialog(Signallable, Loggable):
diff --git a/pitivi/ui/gstwidget.py b/pitivi/ui/gstwidget.py
index 67fb3e5..6e241ff 100644
--- a/pitivi/ui/gstwidget.py
+++ b/pitivi/ui/gstwidget.py
@@ -30,7 +30,7 @@ import os
import ges
from gettext import gettext as _
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
from pitivi.configure import get_ui_dir
import pitivi.ui.dynamic as dynamic
from pitivi.ui.common import SPACING
diff --git a/pitivi/ui/mainwindow.py b/pitivi/ui/mainwindow.py
index 313a75a..527239f 100644
--- a/pitivi/ui/mainwindow.py
+++ b/pitivi/ui/mainwindow.py
@@ -35,7 +35,7 @@ from gettext import gettext as _
from gtk import RecentManager
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
from pitivi.settings import GlobalSettings
from pitivi.sourcelist import SourceListError
diff --git a/pitivi/ui/previewer.py b/pitivi/ui/previewer.py
index 1d7a9c1..40cf9ad 100644
--- a/pitivi/ui/previewer.py
+++ b/pitivi/ui/previewer.py
@@ -33,7 +33,7 @@ from pitivi.configure import get_pixmap_dir
from pitivi.signalinterface import Signallable
from pitivi.settings import GlobalSettings
from pitivi.ui.zoominterface import Zoomable
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
from pitivi.thumbnailcache import ThumbnailCache
from pitivi.ui.prefs import PreferencesDialog
from pitivi.receiver import receiver, handler
diff --git a/pitivi/ui/ruler.py b/pitivi/ui/ruler.py
index 0f8145a..58f18c6 100644
--- a/pitivi/ui/ruler.py
+++ b/pitivi/ui/ruler.py
@@ -30,7 +30,7 @@ import gst
from pitivi.utils.misc import Seeker
from pitivi.ui.zoominterface import Zoomable
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
from pitivi.utils.misc import time_to_string
diff --git a/pitivi/ui/sourcelist.py b/pitivi/ui/sourcelist.py
index 7fd570c..74cb2eb 100644
--- a/pitivi/ui/sourcelist.py
+++ b/pitivi/ui/sourcelist.py
@@ -42,7 +42,7 @@ from pitivi.ui.pathwalker import PathWalker, quote_uri
from pitivi.ui.filelisterrordialog import FileListErrorDialog
from pitivi.ui.common import beautify_info, info_name, \
SPACING, PADDING
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
from pitivi.ui.filechooserpreview import PreviewWidget
SHOW_TREEVIEW = 1
diff --git a/pitivi/ui/timeline.py b/pitivi/ui/timeline.py
index 45ee0a4..47208f5 100644
--- a/pitivi/ui/timeline.py
+++ b/pitivi/ui/timeline.py
@@ -35,7 +35,7 @@ from gettext import gettext as _
from zoominterface import Zoomable
from pitivi.check import soft_deps
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
from timelinecanvas import TimelineCanvas
from timelinecontrols import TimelineControls
from pitivi.effects import AUDIO_EFFECT, VIDEO_EFFECT
diff --git a/pitivi/ui/timelinecanvas.py b/pitivi/ui/timelinecanvas.py
index 778d13a..01281ae 100644
--- a/pitivi/ui/timelinecanvas.py
+++ b/pitivi/ui/timelinecanvas.py
@@ -23,7 +23,7 @@ import gtk
import goocanvas
from gettext import gettext as _
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
from pitivi.receiver import receiver, handler
from pitivi.ui.track import Track
from pitivi.ui.trackobject import TrackObject
diff --git a/pitivi/ui/timelinecontrols.py b/pitivi/ui/timelinecontrols.py
index 37ebcdc..eadd6d3 100644
--- a/pitivi/ui/timelinecontrols.py
+++ b/pitivi/ui/timelinecontrols.py
@@ -2,7 +2,7 @@ import gtk
from pitivi.receiver import receiver, handler
from gettext import gettext as _
from common import LAYER_HEIGHT_EXPANDED, LAYER_SPACING
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
TRACK_CONTROL_WIDTH = 75
diff --git a/pitivi/ui/track.py b/pitivi/ui/track.py
index c316e6f..0dc57c1 100644
--- a/pitivi/ui/track.py
+++ b/pitivi/ui/track.py
@@ -24,7 +24,7 @@ import goocanvas
import ges
import gobject
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
from pitivi.ui.zoominterface import Zoomable
from pitivi.receiver import receiver, handler
from pitivi.ui.trackobject import TrackObject
diff --git a/pitivi/ui/trackobject.py b/pitivi/ui/trackobject.py
index 4506d09..449e30c 100644
--- a/pitivi/ui/trackobject.py
+++ b/pitivi/ui/trackobject.py
@@ -14,7 +14,7 @@ from common import LAYER_HEIGHT_EXPANDED, LAYER_HEIGHT_COLLAPSED
from common import LAYER_SPACING, unpack_cairo_pattern, unpack_cairo_gradient
from pitivi.ui.point import Point
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
from pitivi.settings import GlobalSettings
from pitivi.receiver import receiver, handler
from pitivi.ui.prefs import PreferencesDialog
diff --git a/pitivi/ui/viewer.py b/pitivi/ui/viewer.py
index afb273d..a82d598 100644
--- a/pitivi/ui/viewer.py
+++ b/pitivi/ui/viewer.py
@@ -27,7 +27,7 @@ import cairo
from gettext import gettext as _
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
from pitivi.settings import GlobalSettings
from pitivi.utils.misc import togglePlayback
from pitivi.ui.common import SPACING, hex_to_rgb
diff --git a/pitivi/undo/undo.py b/pitivi/undo/undo.py
index bcf6582..f6b14a3 100644
--- a/pitivi/undo/undo.py
+++ b/pitivi/undo/undo.py
@@ -20,7 +20,7 @@
# Boston, MA 02110-1301, USA.
from pitivi.signalinterface import Signallable
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
class UndoError(Exception):
diff --git a/pitivi/utils/Makefile.am b/pitivi/utils/Makefile.am
index 1d1f076..afc42b2 100644
--- a/pitivi/utils/Makefile.am
+++ b/pitivi/utils/Makefile.am
@@ -6,6 +6,7 @@ utils_PYTHON = \
alignalgs.py \
extract.py \
timeline.py \
+ loggable.py \
misc.py
clean-local:
diff --git a/pitivi/utils/align.py b/pitivi/utils/align.py
index 9102b6a..55343bf 100644
--- a/pitivi/utils/align.py
+++ b/pitivi/utils/align.py
@@ -33,7 +33,7 @@ except ImportError:
import gobject
import gst
from pitivi.utils.misc import beautify_ETA, call_false
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
from pitivi.utils.alignalgs import rigidalign
diff --git a/pitivi/utils/extract.py b/pitivi/utils/extract.py
index cd01b79..9467b54 100644
--- a/pitivi/utils/extract.py
+++ b/pitivi/utils/extract.py
@@ -30,7 +30,7 @@ import gst
from collections import deque
from pitivi.elements.singledecodebin import SingleDecodeBin
from pitivi.elements.extractionsink import ExtractionSink
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
from pitivi.utils.misc import pipeline
diff --git a/pitivi/log/log.py b/pitivi/utils/loggable.py
similarity index 74%
rename from pitivi/log/log.py
rename to pitivi/utils/loggable.py
index 6cb6cfa..ad1f3a7 100644
--- a/pitivi/log/log.py
+++ b/pitivi/utils/loggable.py
@@ -1,20 +1,23 @@
-# -*- Mode: Python; test-case-name: test_log -*-
-# vi:si:et:sw=4:sts=4:ts=4
-
-# This file is released under the standard PSF license.
-
-"""
-Logging module.
-
-Five levels of log information are defined.
-These are, in order of decreasing verbosity: log, debug, info, warning, error.
-
-This module provides a Loggable class for objects, as well as various
-convenience methods for logging in general, and for logging with Twisted
-and failures in particular.
-
-Maintainer: U{Thomas Vander Stichele <thomas at apestaart dot org>}
-"""
+# PiTiVi , Non-linear video editor
+#
+# pitivi/log/loggable.py
+#
+# Copyright (c) 2009, Alessandro Decina <alessandro decina collabora co uk>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+# Boston, MA 02110-1301, USA.
import errno
import sys
@@ -25,6 +28,7 @@ import types
import traceback
import thread
+
# environment variables controlling levels for each category
_DEBUG = "*:1"
# name of the environment variable controlling our logging
@@ -63,6 +67,208 @@ _FORMATTED_LEVELS = []
_LEVEL_NAMES = ['ERROR', 'WARN', 'INFO', 'DEBUG', 'LOG']
+class TerminalController:
+ """
+ A class that can be used to portably generate formatted output to
+ a terminal.
+
+ `TerminalController` defines a set of instance variables whose
+ values are initialized to the control sequence necessary to
+ perform a given action. These can be simply included in normal
+ output to the terminal:
+
+ >>> term = TerminalController()
+ >>> print 'This is '+term.GREEN+'green'+term.NORMAL
+
+ Alternatively, the `render()` method can used, which replaces
+ '${action}' with the string required to perform 'action':
+
+ >>> term = TerminalController()
+ >>> print term.render('This is ${GREEN}green${NORMAL}')
+
+ If the terminal doesn't support a given action, then the value of
+ the corresponding instance variable will be set to ''. As a
+ result, the above code will still work on terminals that do not
+ support color, except that their output will not be colored.
+ Also, this means that you can test whether the terminal supports a
+ given action by simply testing the truth value of the
+ corresponding instance variable:
+
+ >>> term = TerminalController()
+ >>> if term.CLEAR_SCREEN:
+ ... print 'This terminal supports clearning the screen.'
+
+ Finally, if the width and height of the terminal are known, then
+ they will be stored in the `COLS` and `LINES` attributes.
+ """
+ # Cursor movement:
+ BOL = '' # : Move the cursor to the beginning of the line
+ UP = '' # : Move the cursor up one line
+ DOWN = '' # : Move the cursor down one line
+ LEFT = '' # : Move the cursor left one char
+ RIGHT = '' # : Move the cursor right one char
+
+ # Deletion:
+ CLEAR_SCREEN = '' # : Clear the screen and move to home position
+ CLEAR_EOL = '' # : Clear to the end of the line.
+ CLEAR_BOL = '' # : Clear to the beginning of the line.
+ CLEAR_EOS = '' # : Clear to the end of the screen
+
+ # Output modes:
+ BOLD = '' # : Turn on bold mode
+ BLINK = '' # : Turn on blink mode
+ DIM = '' # : Turn on half-bright mode
+ REVERSE = '' # : Turn on reverse-video mode
+ NORMAL = '' # : Turn off all modes
+
+ # Cursor display:
+ HIDE_CURSOR = '' # : Make the cursor invisible
+ SHOW_CURSOR = '' # : Make the cursor visible
+
+ # Terminal size:
+ COLS = None # : Width of the terminal (None for unknown)
+ LINES = None # : Height of the terminal (None for unknown)
+
+ # Foreground colors:
+ BLACK = BLUE = GREEN = CYAN = RED = MAGENTA = YELLOW = WHITE = ''
+
+ # Background colors:
+ BG_BLACK = BG_BLUE = BG_GREEN = BG_CYAN = ''
+ BG_RED = BG_MAGENTA = BG_YELLOW = BG_WHITE = ''
+
+ _STRING_CAPABILITIES = """
+ BOL=cr UP=cuu1 DOWN=cud1 LEFT=cub1 RIGHT=cuf1
+ CLEAR_SCREEN=clear CLEAR_EOL=el CLEAR_BOL=el1 CLEAR_EOS=ed BOLD=bold
+ BLINK=blink DIM=dim REVERSE=rev UNDERLINE=smul NORMAL=sgr0
+ HIDE_CURSOR=cinvis SHOW_CURSOR=cnorm""".split()
+ _COLORS = """BLACK BLUE GREEN CYAN RED MAGENTA YELLOW WHITE""".split()
+ _ANSICOLORS = "BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE".split()
+
+ def __init__(self, term_stream=sys.stdout):
+ """
+ Create a `TerminalController` and initialize its attributes
+ with appropriate values for the current terminal.
+ `term_stream` is the stream that will be used for terminal
+ output; if this stream is not a tty, then the terminal is
+ assumed to be a dumb terminal (i.e., have no capabilities).
+ """
+ # Curses isn't available on all platforms
+ try:
+ import curses
+ except ImportError:
+ return
+
+ # If the stream isn't a tty, then assume it has no capabilities.
+ if not term_stream.isatty():
+ return
+
+ # Check the terminal type. If we fail, then assume that the
+ # terminal has no capabilities.
+ try:
+ curses.setupterm()
+ except:
+ return
+
+ # Look up numeric capabilities.
+ self.COLS = curses.tigetnum('cols')
+ self.LINES = curses.tigetnum('lines')
+
+ # Look up string capabilities.
+ for capability in self._STRING_CAPABILITIES:
+ (attrib, cap_name) = capability.split('=')
+ setattr(self, attrib, self._tigetstr(cap_name) or '')
+
+ # Colors
+ set_fg = self._tigetstr('setf')
+ if set_fg:
+ for i, color in zip(range(len(self._COLORS)), self._COLORS):
+ setattr(self, color, curses.tparm(set_fg, i) or '')
+ set_fg_ansi = self._tigetstr('setaf')
+ if set_fg_ansi:
+ for i, color in zip(range(len(self._ANSICOLORS)),
+ self._ANSICOLORS):
+ setattr(self, color, curses.tparm(set_fg_ansi, i) or '')
+ set_bg = self._tigetstr('setb')
+ if set_bg:
+ for i, color in zip(range(len(self._COLORS)), self._COLORS):
+ setattr(self, 'BG_' + color, curses.tparm(set_bg, i) or '')
+ set_bg_ansi = self._tigetstr('setab')
+ if set_bg_ansi:
+ for i, color in zip(range(len(self._ANSICOLORS)),
+ self._ANSICOLORS):
+ setattr(self, 'BG_' + color, curses.tparm(set_bg_ansi, i) or '')
+
+ def _tigetstr(self, cap_name):
+ # String capabilities can include "delays" of the form "$<2>".
+ # For any modern terminal, we should be able to just ignore
+ # these, so strip them out.
+ import curses
+ cap = curses.tigetstr(cap_name) or ''
+ return re.sub(r'\$<\d+>[/*]?', '', cap)
+
+ def render(self, template):
+ """
+ Replace each $-substitutions in the given template string with
+ the corresponding terminal control string (if it's defined) or
+ '' (if it's not).
+ """
+ return re.sub(r'\$\$|\${\w+}', self._render_sub, template)
+
+ def _render_sub(self, match):
+ s = match.group()
+ if s == '$$':
+ return s
+ else:
+ return getattr(self, s[2:-1])
+
+#######################################################################
+# Example use case: progress bar
+#######################################################################
+
+
+class ProgressBar:
+ """
+ A 3-line progress bar, which looks like::
+
+ Header
+ 20% [===========----------------------------------]
+ progress message
+
+ The progress bar is colored, if the terminal supports color
+ output; and adjusts to the width of the terminal.
+ """
+ BAR = '%3d%% ${GREEN}[${BOLD}%s%s${NORMAL}${GREEN}]${NORMAL}\n'
+ HEADER = '${BOLD}${CYAN}%s${NORMAL}\n\n'
+
+ def __init__(self, term, header):
+ self.term = term
+ if not (self.term.CLEAR_EOL and self.term.UP and self.term.BOL):
+ raise ValueError("Terminal isn't capable enough -- you "
+ "should use a simpler progress dispaly.")
+ self.width = self.term.COLS or 75
+ self.bar = term.render(self.BAR)
+ self.header = self.term.render(self.HEADER % header.center(self.width))
+ self.cleared = 1 # : true if we haven't drawn the bar yet.
+ self.update(0, '')
+
+ def update(self, percent, message):
+ if self.cleared:
+ sys.stdout.write(self.header)
+ self.cleared = 0
+ n = int((self.width - 10) * percent)
+ sys.stdout.write(
+ self.term.BOL + self.term.UP + self.term.CLEAR_EOL +
+ (self.bar % (100 * percent, '=' * n, '-' * (self.width - 10 - n))) +
+ self.term.CLEAR_EOL + message.center(self.width))
+
+ def clear(self):
+ if not self.cleared:
+ sys.stdout.write(self.term.BOL + self.term.CLEAR_EOL +
+ self.term.UP + self.term.CLEAR_EOL +
+ self.term.UP + self.term.CLEAR_EOL)
+ self.cleared = 1
+
+
def getLevelName(level):
"""
Return the name of a log level.
@@ -710,7 +916,7 @@ def outputToFiles(stdout=None, stderr=None):
# base class for loggable objects
-class Loggable(object):
+class BaseLoggable(object):
"""
Base class for objects that want to be able to log messages with
different level of severity. The levels are, in order from least
@@ -917,7 +1123,7 @@ def logTwisted():
# expects a bound method
-class TwistedLogObserver(Loggable):
+class TwistedLogObserver(BaseLoggable):
"""
Twisted log observer that integrates with our logging.
"""
@@ -971,3 +1177,23 @@ class TwistedLogObserver(Loggable):
def clearIgnores(self):
self._ignoreErrors = []
+
+
+class Loggable(BaseLoggable):
+ def __init__(self, logCategory=None):
+ if logCategory:
+ self.logCategory = logCategory
+ elif not hasattr(self, 'logCategory'):
+ self.logCategory = self.__class__.__name__.lower()
+
+ def logObjectName(self):
+ res = BaseLoggable.logObjectName(self)
+ if not res:
+ return "<%s at 0x%x>" % (self.__class__.__name__, id(self))
+ return res
+
+ def error(self, format, *args):
+ if _canShortcutLogging(self.logCategory, ERROR):
+ return
+ doLog(ERROR, self.logObjectName(), self.logCategory,
+ format, self.logFunction(*args), where=-2)
diff --git a/pitivi/utils/misc.py b/pitivi/utils/misc.py
index 9de4a1c..76b81f7 100644
--- a/pitivi/utils/misc.py
+++ b/pitivi/utils/misc.py
@@ -33,7 +33,7 @@ import time
from pitivi.configure import APPMANUALURL_OFFLINE, APPMANUALURL_ONLINE
from pitivi.signalinterface import Signallable
-import pitivi.log.log as log
+import pitivi.utils.loggable as log
from gettext import ngettext
try:
import cProfile
diff --git a/pitivi/utils/timeline.py b/pitivi/utils/timeline.py
index 981a698..b98f425 100644
--- a/pitivi/utils/timeline.py
+++ b/pitivi/utils/timeline.py
@@ -25,7 +25,7 @@ import ges
from gst import SECOND
from pitivi.utils.misc import infinity
-from pitivi.log.loggable import Loggable
+from pitivi.utils.loggable import Loggable
from pitivi.signalinterface import Signallable
#from pitivi.utils.align import AutoAligner
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 0ec97d3..45e3695 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -13,6 +13,7 @@ tests = \
test_undo.py \
test_utils.py \
test_system.py \
+ test_log.py \
test_system_gnome.py
integration_tests = \
diff --git a/tests/runtests.py b/tests/runtests.py
index e3f7c2e..a94a794 100644
--- a/tests/runtests.py
+++ b/tests/runtests.py
@@ -21,7 +21,7 @@ verbosity = 1
if 'VERBOSE' in os.environ:
descriptions = 2
verbosity = 2
-from pitivi.log import log
+from pitivi.utils import loggable as log
log.init('PITIVI_DEBUG', 1)
# Make available to configure.py the top level dir.
diff --git a/tests/test_log.py b/tests/test_log.py
new file mode 100644
index 0000000..103757c
--- /dev/null
+++ b/tests/test_log.py
@@ -0,0 +1,288 @@
+# -*- Mode: Python; test-case-name: test_log -*-
+# vi:si:et:sw=4:sts=4:ts=4
+#
+# Flumotion - a streaming media server
+# Copyright (C) 2004,2005,2006,2007 Fluendo, S.L. (www.fluendo.com).
+# All rights reserved.
+
+# This file may be distributed and/or modified under the terms of
+# the GNU General Public License version 2 as published by
+# the Free Software Foundation.
+# This file is distributed without any warranty; without even the implied
+# warranty of merchantability or fitness for a particular purpose.
+# See "LICENSE.GPL" in the source distribution for more information.
+
+# Licensees having purchased or holding a valid Flumotion Advanced
+# Streaming Server license may use this file in accordance with the
+# Flumotion Advanced Streaming Server Commercial License Agreement.
+# See "LICENSE.Flumotion" in the source distribution for more information.
+
+# Headers in this file shall remain intact.
+
+
+###
+# FIXME me all
+###
+#from twisted.trial import unittest
+
+#from pitivi.utils import loggable as log
+
+#__version__ = "$Rev: 7162 $"
+
+
+#class LogTester(log.Loggable):
+ #logCategory = 'testlog'
+
+
+#class LogFunctionTester(log.Loggable):
+
+ #def logFunction(self, format, *args):
+ #return (("override " + format), ) + args[1:]
+
+
+#class TestLog(unittest.TestCase):
+
+ #def setUp(self):
+ #self.category = self.level = self.message = None
+ #self.tester = LogTester()
+ ## we want to remove the default handler so it doesn't show up stuff
+ #log.reset()
+
+ ## just test for parsing semi- or non-valid FLU_DEBUG variables
+
+ #def testSetDebug(self):
+ #log.setDebug(":5")
+ #log.setDebug("*")
+ #log.setDebug("5")
+
+ ## test for adding a log handler
+
+ #def handler(self, level, object, category, file, line, message):
+ #self.level = level
+ #self.object = object
+ #self.category = category
+ #self.file = file
+ #self.line = line
+ #self.message = message
+
+ #def testLimitInvisible(self):
+ #log.setDebug("testlog:3")
+ #log.addLimitedLogHandler(self.handler)
+
+ ## log 2 we shouldn't get
+ #self.tester.log("not visible")
+ #assert not self.category
+ #assert not self.level
+ #assert not self.message
+
+ #self.tester.debug("not visible")
+ #assert not self.category
+ #assert not self.level
+ #assert not self.message
+
+ #def testLimitedVisible(self):
+ #log.setDebug("testlog:3")
+ #log.addLimitedLogHandler(self.handler)
+
+ ## log 3 we should get
+ #self.tester.info("visible")
+ #assert self.category == 'testlog'
+ #assert self.level == log.INFO
+ #assert self.message == 'visible'
+
+ #self.tester.warning("also visible")
+ #assert self.category == 'testlog'
+ #assert self.level == log.WARN
+ #assert self.message == 'also visible'
+
+ #def testFormatStrings(self):
+ #log.setDebug("testlog:3")
+ #log.addLimitedLogHandler(self.handler)
+
+ #self.tester.info("%d %s", 42, 'the answer')
+ #assert self.category == 'testlog'
+ #assert self.level == log.INFO
+ #assert self.message == '42 the answer'
+
+ #def testLimitedError(self):
+ #log.setDebug("testlog:3")
+ #log.addLimitedLogHandler(self.handler)
+
+ #self.assertRaises(SystemExit, self.tester.error, "error")
+ #assert self.category == 'testlog'
+ #assert self.level == log.ERROR
+ #assert self.message == 'error'
+
+ #def testLogHandlerLimitedLevels(self):
+ #log.setDebug("testlog:3")
+ #log.addLimitedLogHandler(self.handler)
+
+ ## now try debug and log again too
+ #log.setDebug("testlog:5")
+
+ #self.tester.debug("debug")
+ #assert self.category == 'testlog'
+ #assert self.level == log.DEBUG
+ #assert self.message == 'debug'
+
+ #self.tester.log("log")
+ #assert self.category == 'testlog'
+ #assert self.level == log.LOG
+ #assert self.message == 'log'
+
+ ## test that we get all log messages
+
+ #def testLogHandler(self):
+ #log.setDebug("testlog:3")
+ #log.addLogHandler(self.handler)
+
+ #self.tester.log("visible")
+ #assert self.message == 'visible'
+
+ #self.tester.warning("also visible")
+ #assert self.message == 'also visible'
+
+
+#class TestOwnLogHandler(unittest.TestCase):
+
+ #def setUp(self):
+ #self.category = self.level = self.message = None
+ #self.tester = LogFunctionTester()
+
+ #def handler(self, level, object, category, file, line, message):
+ #self.level = level
+ #self.object = object
+ #self.category = category
+ #self.file = file
+ #self.line = line
+ #self.message = message
+
+ ## test if our own log handler correctly mangles the message
+
+ #def testOwnLogHandlerLimited(self):
+ #log.setDebug("testlog:3")
+ #log.addLogHandler(self.handler)
+
+ #self.tester.log("visible")
+ #assert self.message == 'override visible'
+
+ #def testLogHandlerAssertion(self):
+ #self.assertRaises(TypeError, log.addLimitedLogHandler, None)
+
+
+#class TestGetExceptionMessage(unittest.TestCase):
+
+ #def func3(self):
+ #self.func2()
+
+ #def func2(self):
+ #self.func1()
+
+ #def func1(self):
+ #raise TypeError("I am in func1")
+
+ #def testLevel2(self):
+ #try:
+ #self.func2()
+ #self.fail()
+ #except TypeError, e:
+ #self.verifyException(e)
+
+ #def testLevel3(self):
+ #try:
+ #self.func3()
+ #self.fail()
+ #except TypeError, e:
+ #self.verifyException(e)
+
+ #def verifyException(self, e):
+ #message = log.getExceptionMessage(e)
+ #self.failUnless("func1()" in message)
+ #self.failUnless("test_log.py" in message)
+ #self.failUnless("TypeError" in message)
+
+
+#class TestLogSettings(unittest.TestCase):
+
+ #def testSet(self):
+ #old = log.getLogSettings()
+ #log.setDebug('*:5')
+ #self.assertNotEquals(old, log.getLogSettings())
+
+ #log.setLogSettings(old)
+ #self.assertEquals(old, log.getLogSettings())
+
+
+#class TestWriteMark(unittest.TestCase):
+
+ #def handler(self, level, object, category, file, line, message):
+ #self.level = level
+ #self.object = object
+ #self.category = category
+ #self.file = file
+ #self.line = line
+ #self.message = message
+
+ #def testWriteMarkInDebug(self):
+ #loggable = log.Loggable()
+ #log.setDebug("4")
+ #log.addLogHandler(self.handler)
+ #marker = 'test'
+ #loggable.writeMarker(marker, log.DEBUG)
+ #self.assertEquals(self.message, marker)
+
+ #def testWriteMarkInWarn(self):
+ #loggable = log.Loggable()
+ #log.setDebug("2")
+ #log.addLogHandler(self.handler)
+ #marker = 'test'
+ #loggable.writeMarker(marker, log.WARN)
+ #self.assertEquals(self.message, marker)
+
+ #def testWriteMarkInInfo(self):
+ #loggable = log.Loggable()
+ #log.setDebug("3")
+ #log.addLogHandler(self.handler)
+ #marker = 'test'
+ #loggable.writeMarker(marker, log.INFO)
+ #self.assertEquals(self.message, marker)
+
+ #def testWriteMarkInLog(self):
+ #loggable = log.Loggable()
+ #log.setDebug("5")
+ #log.addLogHandler(self.handler)
+ #marker = 'test'
+ #loggable.writeMarker(marker, log.LOG)
+ #self.assertEquals(self.message, marker)
+
+ #def testWriteMarkInError(self):
+ #loggable = log.Loggable()
+ #log.setDebug("4")
+ #log.addLogHandler(self.handler)
+ #marker = 'test'
+ #self.assertRaises(SystemExit, loggable.writeMarker, marker, log.ERROR)
+ #self.assertEquals(self.message, marker)
+
+
+#class TestLogNames(unittest.TestCase):
+
+ #def testGetLevelNames(self):
+ #self.assertEquals(['ERROR', 'WARN', 'INFO', 'DEBUG', 'LOG'],
+ #log.getLevelNames())
+
+ #def testGetLevelCode(self):
+ #self.assertEquals(1, log.getLevelInt('ERROR'))
+ #self.assertEquals(2, log.getLevelInt('WARN'))
+ #self.assertEquals(3, log.getLevelInt('INFO'))
+ #self.assertEquals(4, log.getLevelInt('DEBUG'))
+ #self.assertEquals(5, log.getLevelInt('LOG'))
+
+ #def testGetLevelName(self):
+ #self.assertEquals('ERROR', log.getLevelName(1))
+ #self.assertEquals('WARN', log.getLevelName(2))
+ #self.assertEquals('INFO', log.getLevelName(3))
+ #self.assertEquals('DEBUG', log.getLevelName(4))
+ #self.assertEquals('LOG', log.getLevelName(5))
+
+#if __name__ == '__main__':
+ #unittest.main()
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]