[Zope3-checkins] CVS: Zope3/src/zope/exceptions - __init__.py:1.2 _duplicate.py:1.2 _forbidden.py:1.2 _notfounderror.py:1.2 _zope_error.py:1.2 exceptionformatter.py:1.2 interfaces.py:1.2 unauthorized.py:1.2

Jim Fulton jim@zope.com
Wed, 25 Dec 2002 09:14:10 -0500


Update of /cvs-repository/Zope3/src/zope/exceptions
In directory cvs.zope.org:/tmp/cvs-serv15352/src/zope/exceptions

Added Files:
	__init__.py _duplicate.py _forbidden.py _notfounderror.py 
	_zope_error.py exceptionformatter.py interfaces.py 
	unauthorized.py 
Log Message:
Grand renaming:

- Renamed most files (especially python modules) to lower case.

- Moved views and interfaces into separate hierarchies within each
  project, where each top-level directory under the zope package
  is a separate project.

- Moved everything to src from lib/python.

  lib/python will eventually go away. I need access to the cvs
  repository to make this happen, however.

There are probably some bits that are broken. All tests pass
and zope runs, but I haven't tried everything. There are a number
of cleanups I'll work on tomorrow.



=== Zope3/src/zope/exceptions/__init__.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:14:09 2002
+++ Zope3/src/zope/exceptions/__init__.py	Wed Dec 25 09:13:38 2002
@@ -0,0 +1,26 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""General exceptions that wish they were standard exceptions
+
+These exceptions are so general purpose that they don't belong in Zope
+application-specific packages.
+
+$Id$
+"""
+
+from zope.exceptions._zope_error import ZopeError
+from zope.exceptions.unauthorized import Unauthorized
+from zope.exceptions._notfounderror import NotFoundError
+from zope.exceptions._forbidden import Forbidden, ForbiddenAttribute
+from zope.exceptions._duplicate import DuplicationError


=== Zope3/src/zope/exceptions/_duplicate.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:14:09 2002
+++ Zope3/src/zope/exceptions/_duplicate.py	Wed Dec 25 09:13:38 2002
@@ -0,0 +1,20 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+$Id$
+"""
+from zope.exceptions import ZopeError
+
+class DuplicationError(ZopeError):
+    """A duplicate registration was attempted"""


=== Zope3/src/zope/exceptions/_forbidden.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:14:09 2002
+++ Zope3/src/zope/exceptions/_forbidden.py	Wed Dec 25 09:13:38 2002
@@ -0,0 +1,25 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+$Id$
+"""
+from zope.exceptions import ZopeError
+
+class Forbidden(ZopeError):
+    """A resource cannot be accessed under any circumstances
+    """
+
+class ForbiddenAttribute(Forbidden, AttributeError):
+    """An attribute is unavailable because it is forbidden (private)
+    """


=== Zope3/src/zope/exceptions/_notfounderror.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:14:09 2002
+++ Zope3/src/zope/exceptions/_notfounderror.py	Wed Dec 25 09:13:38 2002
@@ -0,0 +1,21 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+$Id$
+"""
+from zope.exceptions import ZopeError
+
+class NotFoundError(ZopeError, KeyError):
+    """A resource could not be found.
+    """


=== Zope3/src/zope/exceptions/_zope_error.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:14:09 2002
+++ Zope3/src/zope/exceptions/_zope_error.py	Wed Dec 25 09:13:38 2002
@@ -0,0 +1,20 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Base class for Zope application errors.
+
+$Id$
+"""
+
+class ZopeError( Exception ):
+    """ Generic base class for Zope errors."""


=== Zope3/src/zope/exceptions/exceptionformatter.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:14:09 2002
+++ Zope3/src/zope/exceptions/exceptionformatter.py	Wed Dec 25 09:13:38 2002
@@ -0,0 +1,239 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""An exception formatter that shows traceback supplements and traceback info,
+optionally in HTML.
+
+$Id$
+"""
+
+import sys
+import cgi
+
+
+DEBUG_EXCEPTION_FORMATTER = 1
+
+
+class TextExceptionFormatter:
+
+    line_sep = '\n'
+    show_revisions = 0
+
+    def __init__(self, limit=None):
+        self.limit = limit
+
+    def escape(self, s):
+        return s
+
+    def getPrefix(self):
+        return 'Traceback (innermost last):'
+
+    def getLimit(self):
+        limit = self.limit
+        if limit is None:
+            limit = getattr(sys, 'tracebacklimit', None)
+        return limit
+
+    def getRevision(self, globals):
+        if not self.show_revisions:
+            return None
+        revision = globals.get('__revision__', None)
+        if revision is None:
+            # Incorrect but commonly used spelling
+            revision = globals.get('__version__', None)
+
+        if revision is not None:
+            try:
+                revision = str(revision).strip()
+            except:
+                revision = '???'
+        return revision
+
+    def formatSupplementLine(self, line):
+        return '   - %s' % line
+
+    def formatSourceURL(self, url):
+        return [self.formatSupplementLine(url)]
+
+    def formatSupplement(self, supplement, tb):
+        result = []
+        fmtLine = self.formatSupplementLine
+
+        url = getattr(supplement, 'source_url', None)
+        if url is not None:
+            result.extend(self.formatSourceURL(url))
+
+        line = getattr(supplement, 'line', 0)
+        if line == -1:
+            line = tb.tb_lineno
+        col = getattr(supplement, 'column', -1)
+        if line:
+            if col is not None and col >= 0:
+                result.append(fmtLine('Line %s, Column %s' % (
+                    line, col)))
+            else:
+                result.append(fmtLine('Line %s' % line))
+        elif col is not None and col >= 0:
+            result.append(fmtLine('Column %s' % col))
+
+        expr = getattr(supplement, 'expression', None)
+        if expr:
+            result.append(fmtLine('Expression: %s' % expr))
+
+        warnings = getattr(supplement, 'warnings', None)
+        if warnings:
+            for warning in warnings:
+                result.append(fmtLine('Warning: %s' % warning))
+
+        getInfo = getattr(supplement, 'getInfo', None)
+        if getInfo is not None:
+            try:
+                extra = getInfo()
+                if extra:
+                    result.append(extra)
+            except:
+                if DEBUG_EXCEPTION_FORMATTER:
+                    import traceback
+                    traceback.print_exc()
+                # else just swallow the exception.
+        return result
+
+    def formatTracebackInfo(self, tbi):
+        return self.formatSupplementLine('__traceback_info__: %s' % tbi)
+
+    def formatLine(self, tb):
+        f = tb.tb_frame
+        lineno = tb.tb_lineno
+        co = f.f_code
+        filename = co.co_filename
+        name = co.co_name
+        locals = f.f_locals
+        globals = f.f_globals
+        modname = globals.get('__name__', filename)
+
+        s = '  Module %s, line %d' % (modname, lineno)
+
+        revision = self.getRevision(globals)
+        if revision:
+            s = s + ', rev. %s' % revision
+
+        s = s + ', in %s' % name
+
+        result = []
+        result.append(self.escape(s))
+
+        # Output a traceback supplement, if any.
+        if '__traceback_supplement__' in locals:
+            # Use the supplement defined in the function.
+            tbs = locals['__traceback_supplement__']
+        elif '__traceback_supplement__' in globals:
+            # Use the supplement defined in the module.
+            # This is used by Scripts (Python).
+            tbs = globals['__traceback_supplement__']
+        else:
+            tbs = None
+        if tbs is not None:
+            factory = tbs[0]
+            args = tbs[1:]
+            try:
+                supp = factory(*args)
+                result.extend(self.formatSupplement(supp, tb))
+            except:
+                if DEBUG_EXCEPTION_FORMATTER:
+                    import traceback
+                    traceback.print_exc()
+                # else just swallow the exception.
+
+        try:
+            tbi = locals.get('__traceback_info__', None)
+            if tbi is not None:
+                result.append(self.formatTracebackInfo(tbi))
+        except:
+            if DEBUG_EXCEPTION_FORMATTER:
+                import traceback
+                traceback.print_exc()
+            # else just swallow the exception.
+
+        return self.line_sep.join(result)
+
+    def formatExceptionOnly(self, etype, value):
+        import traceback
+        return self.line_sep.join(
+            traceback.format_exception_only(etype, value))
+
+    def formatLastLine(self, exc_line):
+        return self.escape(exc_line)
+
+    def formatException(self, etype, value, tb):
+        # The next line provides a way to detect recursion.
+        __exception_formatter__ = 1
+        result = [self.getPrefix() + '\n']
+        limit = self.getLimit()
+        n = 0
+        while tb is not None and (limit is None or n < limit):
+            if tb.tb_frame.f_locals.get('__exception_formatter__'):
+                # Stop recursion.
+                result.append('(Recursive formatException() stopped)\n')
+                break
+            line = self.formatLine(tb)
+            result.append(line + '\n')
+            tb = tb.tb_next
+            n = n + 1
+        exc_line = self.formatExceptionOnly(etype, value)
+        result.append(self.formatLastLine(exc_line))
+        return result
+
+
+
+class HTMLExceptionFormatter (TextExceptionFormatter):
+
+    line_sep = '<br />\r\n'
+
+    def escape(self, s):
+        return cgi.escape(s)
+
+    def getPrefix(self):
+        return '<p>Traceback (innermost last):\r\n<ul>'
+
+    def formatSupplementLine(self, line):
+        return '<b>%s</b>' % self.escape(str(line))
+
+    def formatTracebackInfo(self, tbi):
+        s = self.escape(str(tbi))
+        s = s.replace('\n', self.line_sep)
+        return '__traceback_info__: %s' % s
+
+    def formatLine(self, tb):
+        line = TextExceptionFormatter.formatLine(self, tb)
+        return '<li>%s</li>' % line
+
+    def formatLastLine(self, exc_line):
+        return '</ul>%s</p>' % self.escape(exc_line)
+
+
+
+limit = 200
+
+if hasattr(sys, 'tracebacklimit'):
+    limit = min(limit, sys.tracebacklimit)
+
+text_formatter = TextExceptionFormatter(limit)
+html_formatter = HTMLExceptionFormatter(limit)
+
+
+def format_exception(t, v, tb, limit=None, as_html=0):
+    if as_html:
+        fmt = html_formatter
+    else:
+        fmt = text_formatter
+    return fmt.formatException(t, v, tb)


=== Zope3/src/zope/exceptions/interfaces.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:14:09 2002
+++ Zope3/src/zope/exceptions/interfaces.py	Wed Dec 25 09:13:38 2002
@@ -0,0 +1,82 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""ITracebackSupplement interface definition.
+
+$Id$
+"""
+
+
+from zope.interface import Interface, Attribute
+
+class ITracebackSupplement(Interface):
+    """Provides valuable information to supplement an exception traceback.
+
+    The interface is geared toward providing meaningful feedback when
+    exceptions occur in user code written in mini-languages like
+    Zope page templates and restricted Python scripts.
+    """
+
+    source_url = Attribute(
+        'source_url',
+        """Optional.  Set to URL of the script where the exception occurred.
+
+        Normally this generates a URL in the traceback that the user
+        can visit to manage the object.  Set to None if unknown or
+        not available.
+        """
+        )
+
+    line = Attribute(
+        'line',
+        """Optional.  Set to the line number (>=1) where the exception
+        occurred.
+
+        Set to 0 or None if the line number is unknown.
+        """
+        )
+
+    column = Attribute(
+        'column',
+        """Optional.  Set to the column offset (>=0) where the exception
+        occurred.
+
+        Set to None if the column number is unknown.
+        """
+        )
+
+    expression = Attribute(
+        'expression',
+        """Optional.  Set to the expression that was being evaluated.
+
+        Set to None if not available or not applicable.
+        """
+        )
+
+    warnings = Attribute(
+        'warnings',
+        """Optional.  Set to a sequence of warning messages.
+
+        Set to None if not available, not applicable, or if the exception
+        itself provides enough information.
+        """
+        )
+
+
+    def getInfo(as_html=0):
+        """Optional.  Returns a string containing any other useful info.
+
+        If as_html is set, the implementation must HTML-quote the result
+        (normally using cgi.escape()).  Returns None to provide no
+        extra info.
+        """


=== Zope3/src/zope/exceptions/unauthorized.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:14:10 2002
+++ Zope3/src/zope/exceptions/unauthorized.py	Wed Dec 25 09:13:38 2002
@@ -0,0 +1,70 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+$Id$
+"""
+
+from types import StringType
+from zope.exceptions import ZopeError
+
+class Unauthorized(ZopeError):
+    """Some user wasn't allowed to access a resource"""
+
+    def __init__(self, message=None, value=None, needed=None, name=None, **kw):
+        """Possible signatures:
+
+        Unauthorized()
+        Unauthorized(message) # Note that message includes a space
+        Unauthorized(name)
+        Unauthorized(name, value)
+        Unauthorized(name, value, needed)
+        Unauthorized(message, value, needed, name)
+
+        Where needed is a mapping objects with items represnting requirements
+        (e.g. {'permission': 'add spam'}). Any extra keyword arguments
+        provides are added to needed.
+        """
+        if name is None and (
+            not isinstance(message, StringType) or len(message.split()) <= 1):
+            # First arg is a name, not a message
+            name=message
+            message=None
+
+        self.name=name
+        self.message=message
+        self.value=value
+
+        if kw:
+            if needed: needed.update(kw)
+            else: needed=kw
+
+        self.needed=needed
+
+    def __str__(self):
+        if self.message is not None: return self.message
+        if self.name is not None:
+            return ("You are not allowed to access %s in this context"
+                    % self.name)
+        elif self.value is not None:
+            return ("You are not allowed to access %s in this context"
+                    % self.getValueName())
+
+
+    def getValueName(self):
+        v=self.value
+        vname=getattr(v, '__name__', None)
+        if vname: return vname
+        c = getattr(v, '__class__', type(v))
+        c = getattr(c, '__name__', 'object')
+        return "a particular %s" % c