summaryrefslogtreecommitdiff
path: root/giscanner/message.py
diff options
context:
space:
mode:
authorJohan Dahlin <johan@gnome.org>2010-09-02 11:04:58 -0300
committerJohan Dahlin <johan@gnome.org>2010-09-02 12:36:51 -0300
commit0b0a3cc7705ca797bc8315ba0815644bef5d30fb (patch)
tree42fbab5d1d08ef0904a9e56bb3c1835cf8326972 /giscanner/message.py
parentfb9924db74e7db4ef2219003e73f9c31f3d9d503 (diff)
downloadgobject-introspection-0b0a3cc7705ca797bc8315ba0815644bef5d30fb.tar.gz
[scanner] add a message module
This module will be used to report warnings, which doesn't explicitly depend on the transformer instance.
Diffstat (limited to 'giscanner/message.py')
-rw-r--r--giscanner/message.py155
1 files changed, 155 insertions, 0 deletions
diff --git a/giscanner/message.py b/giscanner/message.py
new file mode 100644
index 00000000..43555142
--- /dev/null
+++ b/giscanner/message.py
@@ -0,0 +1,155 @@
+#!/usr/bin/env python
+# -*- Mode: Python -*-
+# GObject-Introspection - a framework for introspecting GObject libraries
+# Copyright (C) 2010 Red Hat, Inc.
+# Copyright (C) 2010 Johan Dahlin
+#
+# 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 the Free Software Foundation; either version 2
+# 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+
+import os
+import sys
+
+from . import ast
+
+(WARNING,
+ ERROR,
+ FATAL) = range(3)
+
+class MessageLogger(object):
+ _instance = None
+
+ def __init__(self, namespace):
+ self._cwd = os.getcwd() + os.sep
+ self._namespace = namespace
+ self._enable_warnings = False
+ self._warned = False
+
+ @classmethod
+ def get(cls, *args, **kwargs):
+ if cls._instance is None:
+ cls._instance = cls(*args, **kwargs)
+ return cls._instance
+
+ def enable_warnings(self, enable):
+ self._enable_warnings = enable
+
+ def did_warn(self):
+ return self._warned
+
+ def log(self, log_type, text, file_positions=None, prefix=None):
+ """Log a warning, using optional file positioning information.
+If the warning is related to a ast.Node type, see log_node_warning()."""
+ if not self._enable_warnings:
+ return
+
+ self._warned = True
+
+ if file_positions is None or len(file_positions) == 0:
+ target_file_positions = [('<unknown>', -1, -1)]
+ else:
+ target_file_positions = file_positions
+
+ position_strings = []
+ for (filename, line, column) in target_file_positions:
+ if filename.startswith(self._cwd):
+ filename = filename[len(self._cwd):]
+ if column != -1:
+ position = '%s:%d:%d' % (filename, line, column)
+ elif line != -1:
+ position = '%s:%d' % (filename, line, )
+ else:
+ position = '%s:' % (filename, )
+ position_strings.append(position)
+
+ for position in position_strings[:-1]:
+ print >>sys.stderr, "%s:" % (position, )
+ last_position = position_strings[-1]
+
+ if log_type == WARNING:
+ error_type = "Warning"
+ elif log_type == ERROR:
+ error_type = "Error"
+ elif log_type == FATAL:
+ error_type = "Fatal"
+ if prefix:
+ print >>sys.stderr, \
+'''%s: %s: %s: %s: %s''' % (last_position, error_type, self._namespace.name,
+ prefix, text)
+ else:
+ print >>sys.stderr, \
+'''%s: %s: %s: %s''' % (last_position, error_type, self._namespace.name, text)
+
+
+ if log_type == FATAL:
+ raise SystemExit
+
+ def log_node(self, log_type, node, text, context=None):
+ """Log a warning, using information about file positions from
+the given node. The optional context argument, if given, should be
+another ast.Node type which will also be displayed. If no file position
+information is available from the node, the position data from the
+context will be used."""
+ if hasattr(node, 'file_positions'):
+ if (len(node.file_positions) == 0 and
+ (context is not None) and len(context.file_positions) > 0):
+ file_positions = context.file_positions
+ else:
+ file_positions = node.file_positions
+ else:
+ file_positions = None
+ if not context:
+ text = "context=%r %s" % (node, text)
+
+ if context:
+ if isinstance(context, ast.Function):
+ name = context.symbol
+ else:
+ name = context.name
+ text = "%s: %s" % (name, text)
+ elif len(file_positions) == 0 and hasattr(node, 'name'):
+ text = "(%s)%s: %s" % (node.__class__.__name__, node.name, text)
+
+ self.log(log_type, text, file_positions)
+
+ def log_symbol(self, log_type, symbol, text, **kwargs):
+ """Log a warning in the context of the given symbol."""
+ if symbol.source_filename:
+ file_positions = [(symbol.source_filename, symbol.line, -1)]
+ else:
+ file_positions = None
+ prefix = "symbol=%r" % (symbol.ident, )
+ self.log(log_type, text, file_positions, prefix=prefix, **kwargs)
+
+
+def log_node(log_type, node, text, context=None):
+ ml = MessageLogger.get()
+ ml.log_node(log_type, node, text, context=context)
+
+def warn(text, file_positions=None, prefix=None):
+ ml = MessageLogger.get()
+ ml.log(WARNING, text, file_positions, prefix)
+
+def warn_node(node, text, context=None):
+ log_node(WARNING, node, text, context=context)
+
+def warn_symbol(symbol, text):
+ ml = MessageLogger.get()
+ ml.log_symbol(WARNING, symbol, text)
+
+def fatal(text, file_positions=None, prefix=None):
+ ml = MessageLogger.get()
+ ml.log(FATAL, text, file_positions, prefix)