[Zope3-checkins] CVS: Zope3/src/zope/app - __init__.py:1.2 _app.py:1.2 attributeannotations.py:1.2 configure.zcml:1.2 content_types.py:1.2 datetimeutils.py:1.2 dependable.py:1.2 introspector.py:1.2 meta.zcml:1.2 package_home.py:1.2

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


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

Added Files:
	__init__.py _app.py attributeannotations.py configure.zcml 
	content_types.py datetimeutils.py dependable.py 
	introspector.py meta.zcml package_home.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/app/__init__.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:55 2002
+++ Zope3/src/zope/app/__init__.py	Wed Dec 25 09:12:24 2002
@@ -0,0 +1,18 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""
+Zope application.
+"""
+
+from _app import config, Application


=== Zope3/src/zope/app/_app.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:55 2002
+++ Zope3/src/zope/app/_app.py	Wed Dec 25 09:12:24 2002
@@ -0,0 +1,210 @@
+##############################################################################
+#
+# Copyright (c) 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.
+#
+##############################################################################
+"""Code to initialize the application server
+
+$Id$
+"""
+
+import base64
+from StringIO import StringIO
+from zope.publisher.publish import publish as _publish
+
+__metaclass__ = type
+
+_configured = 0
+def config(file):
+    "Configure site globals"
+    global _configured
+
+    if _configured:
+        return
+
+    from zope.configuration.xmlconfig import XMLConfig
+
+    # Set user to system_user, so we can do anything we want
+    from zope.security.securitymanagement import system_user
+    from zope.security.securitymanagement import newSecurityManager
+    newSecurityManager(system_user)
+
+    # Load server-independent site config
+    XMLConfig(file)()
+
+    # Reset user
+    from zope.security.securitymanagement import noSecurityManager
+    noSecurityManager()
+
+    _configured = 1
+
+def database(db):
+    if type(db) is str:
+        # Database name
+        if db.endswith('.py'):
+            # Python source, exec it
+            globals = {}
+            execfile(db, globals)
+            if 'DB' in globals:
+                db = globals['DB']
+            else:
+                storage = globals['Storage']
+                from zodb.db import DB
+                db = DB(storage)
+        elif db.endswith(".fs"):
+            from zodb.storage.file import FileStorage
+            from zodb.db import DB
+            storage = FileStorage(db)
+            db = DB(storage)
+
+    # XXX When bootstrapping a new database, the following will fail
+    #     while trying to add services when no config_file was passed
+    #     to Application() below.  So, don't do that. :-)
+    from zope.app.startup import bootstrap
+    bootstrap.bootstrapInstance(db)
+
+    return db
+
+class Application:
+
+    def __init__(self, db, config_file=None):
+        if config_file is not None:
+            config(config_file)
+        self.db = database(db)
+
+    def __call__(self):
+        from zope.app.publication.zopepublication import ZopePublication
+        return self.db.open().root()[ZopePublication.root_name]
+
+    __browser_pub = None
+    __TestRequest = None
+
+    def _request(self,
+                 path='/', stdin='', stdout=None, basic=None,
+                 environment = None, form=None):
+
+
+        env = {}
+
+        if stdout is None:
+            stdout = StringIO()
+
+        if type(stdin) is str:
+            stdin = StringIO(stdin)
+
+        p=path.split('?')
+        if len(p)==1:
+            env['PATH_INFO'] = p[0]
+        elif len(p)==2:
+            env['PATH_INFO'], env['QUERY_STRING'] = p
+        else:
+            raise ValueError("Too many ?s in path", path)
+
+        if environment is not None:
+            env.update(environment)
+
+        if basic:
+            env['HTTP_AUTHORIZATION']="Basic %s" % base64.encodestring(basic)
+
+        if self.__TestRequest is None:
+            from zope.publisher.browser import TestRequest
+            from zope.app.publication.browser \
+                 import BrowserPublication
+            from zope.app.publication.zopepublication \
+                 import DebugPublication
+
+            class BrowserPublication(DebugPublication, BrowserPublication):
+                pass
+
+            self.__TestRequest = TestRequest
+            self.__browser_pub = BrowserPublication(self.db)
+
+        request = self.__TestRequest(stdin, stdout, env)
+        request.setPublication(self.__browser_pub)
+        if form:
+            request.update(form)
+
+        return request
+
+    def publish(self, path='/', stdin='', stdout=None, *args, **kw):
+
+        if stdout is None:
+            stdout = StringIO()
+
+        request = self._request(path, stdin, stdout, *args, **kw)
+        _publish(request)
+        stdout.seek(0)
+        print stdout.read()
+
+    def run(self, *args, **kw):
+        request = self._request(*args, **kw)
+        _publish(request, handle_errors = 0)
+
+    def debug(self, *args, **kw):
+
+        import pdb
+
+        class Pdb(pdb.Pdb):
+            def do_pub(self,arg):
+                if hasattr(self,'done_pub'):
+                    print 'pub already done.'
+                else:
+                    self.do_s('')
+                    self.do_s('')
+                    self.do_c('')
+                    self.done_pub=1
+            def do_ob(self,arg):
+                if hasattr(self,'done_ob'):
+                    print 'ob already done.'
+                else:
+                    self.do_pub('')
+                    self.do_c('')
+                    self.done_ob=1
+
+        db=Pdb()
+
+        def fbreak(db, meth):
+            try:
+                meth = meth.im_func
+            except AttributeError:
+                pass
+            code = meth.func_code
+            lineno = getlineno(code)
+            filename = code.co_filename
+            db.set_break(filename,lineno)
+
+        request = self._request(*args, **kw)
+        fbreak(db, _publish)
+        fbreak(db, request.publication.call_wrapper.__call__)
+
+##         dbdata = {'breakpoints':(), 'env':env, 'extra': extra}
+##         b=''
+##         try: b=open('.bobodb','r').read()
+##         except: pass
+##         if b:
+##             exec b in dbdata
+
+##         for b in dbdata['breakpoints']:
+##             if isinstance(b, TupleType):
+##                 apply(db.set_break, b)
+##             else:
+##                 fbreak(db,b)
+
+        db.prompt='pdb> '
+
+        print '* Type c<cr> to jump to published object call.'
+        db.runcall(_publish, request)
+
+try:
+    from codehack import getlineno
+except:
+    def getlineno(code):
+        return code.co_firstlineno


=== Zope3/src/zope/app/attributeannotations.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:56 2002
+++ Zope3/src/zope/app/attributeannotations.py	Wed Dec 25 09:12:24 2002
@@ -0,0 +1,65 @@
+##############################################################################
+#
+# 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 zodb.btrees.OOBTree import OOBTree
+from zope.app.interfaces.annotation import IAnnotations
+from zope.proxy.introspection import removeAllProxies
+from zope.proxy.context import ContextWrapper
+
+class AttributeAnnotations:
+    """
+    Store annotations in the __annotations__ attribute on a
+    IAttributeAnnotatable object.
+    """
+
+    __implements__ = IAnnotations
+
+    def __init__(self, obj):
+        # We could remove all proxies from obj at this point, but
+        # for now, we'll leave it to users of annotations to do that.
+        # Users of annotations will typically need to do their own
+        # unwrapping anyway.
+
+        self.wrapped_obj = obj
+        self.unwrapped_obj = removeAllProxies(obj)
+
+    def __getitem__(self, key):
+        annotations = getattr(self.unwrapped_obj, '__annotations__', {})
+        return ContextWrapper(annotations[key], self.wrapped_obj)
+
+    def get(self, key, default=None):
+        try:
+            value = self.unwrapped_obj.__annotations__.get(key, default)
+        except AttributeError:
+            # I guess default shouldn't be wrapped.
+            return default
+        else:
+            return ContextWrapper(value, self.wrapped_obj)
+
+    def __getattr__(self, name):
+        # this method is for getting methods and attributes of the
+        # mapping object used to store annotations.
+        try:
+            attr = getattr(self.unwrapped_obj.__annotations__, name)
+        except AttributeError:
+            if not hasattr(self.unwrapped_obj, '__annotations__'):
+                annotations = self.unwrapped_obj.__annotations__ = OOBTree()
+                attr = getattr(annotations, name)
+            else:
+                raise
+        return ContextWrapper(attr, self.wrapped_obj)


=== Zope3/src/zope/app/configure.zcml 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:56 2002
+++ Zope3/src/zope/app/configure.zcml	Wed Dec 25 09:12:24 2002
@@ -0,0 +1,79 @@
+<zopeConfigure xmlns='http://namespaces.zope.org/zope'>
+
+<!-- Meta configuration (new directives) -->
+
+  <include file="meta.zcml" />
+
+<!-- Ordinary Application (non-view) configuration) --> 
+
+  <include package="zope.app.component" />
+  <include package="zope.app.security" />
+  <include package="zope.app.event" />
+
+  <serviceType
+     id="SQLDatabaseConnections"
+     interface="zope.app.interfaces.rdb.IConnectionService" 
+     />
+
+  <content class="zope.app.rdb.ZopeConnection">
+    <require
+        permission="zope.ManageContent"
+        interface="zope.app.interfaces.rdb.IZopeConnection" />
+  </content>
+
+  <content class="zope.app.rdb.ZopeCursor">
+    <require
+        permission="zope.ManageContent"
+        interface="zope.app.interfaces.rdb.IZopeCursor" />
+  </content>
+
+  <content class="zope.app.rdb.ResultSet">
+    <require
+        permission="zope.ManageContent"
+        interface="zope.app.interfaces.rdb.IResultSet" />
+  </content>
+
+  <content class="zope.app.rdb.Row">
+    <require
+        permission="zope.ManageContent"
+        attributes="__getattr__" />
+  </content>
+
+  <adapter
+      factory="zope.app.attributeannotations.AttributeAnnotations"
+      provides="zope.app.interfaces.annotation.IAnnotations"
+      for="zope.app.interfaces.annotation.IAttributeAnnotatable" />
+
+
+  <adapter
+      factory="zope.app.introspector.Introspector"
+      permission="zope.View"
+      provides="zope.app.interfaces.introspector.IIntrospector" />
+
+  <adapter
+      factory="zope.app.dependable.Dependable"
+      provides="zope.app.interfaces.dependable.IDependable"
+      for="zope.app.interfaces.annotation.IAnnotatable" />
+
+  <include package="zope.app.container" />
+  <include package="zope.app.content" />
+  <include package="zope.app.services" />
+  <include package="zope.app.applicationcontrol" />
+
+  <include package="zope.app.i18n" />
+  <include package="zope.app.publisher" />
+  <include package="zope.app.rdb" />
+  <include package="zope.app.traversing" />
+  <include package="zope.app.publication" />
+  <include package="zope.app.form" />
+  <include package="zope.app.cache" />
+  <include package="zope.app.dublincore" />
+  <include package="zope.app.startup" />
+  <include package="zope.app.index" />
+
+<!-- Views -->
+
+  <include package="zope.app.browser" />
+  <include package="zope.app.vfs" />
+
+</zopeConfigure>


=== Zope3/src/zope/app/content_types.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:56 2002
+++ Zope3/src/zope/app/content_types.py	Wed Dec 25 09:12:24 2002
@@ -0,0 +1,99 @@
+##############################################################################
+#
+# Copyright (c) 2001 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
+#
+##############################################################################
+"""A utility module for content-type handling."""
+__version__='$Revision$'[11:-2]
+
+import re, mimetypes
+
+find_binary=re.compile('[\0-\7]').search
+
+def text_type(s):
+    # Yuk. See if we can figure out the type by content.
+    s=s.strip()
+    if (s[:6].lower() == '<html>' or s.find('</') > 0):
+        return 'text/html'
+
+    elif s.startswith('<?xml'):
+        return 'text/xml'
+
+    else:
+        return 'text/plain'
+
+
+
+# This gives us a hook to add content types that
+# aren't currently listed in the mimetypes module.
+_addtypes=(
+    ('.mp3', 'audio/mpeg'),
+    ('.ra', 'audio/x-pn-realaudio'),
+    ('.pdf', 'application/pdf'),
+    ('.c', 'text/plain'),
+    ('.bat', 'text/plain'),
+    ('.h', 'text/plain'),
+    ('.pl', 'text/plain'),
+    ('.ksh', 'text/plain'),
+    ('.ram', 'application/x-pn-realaudio'),
+    ('.cdf', 'application-x-cdf'),
+    ('.doc', 'application/msword'),
+    ('.dot', 'application/msword'),
+    ('.wiz', 'application/msword'),
+    ('.xlb', 'application/vnd.ms-excel'),
+    ('.xls', 'application/vnd.ms-excel'),
+    ('.ppa', 'application/vnd.ms-powerpoint'),
+    ('.ppt', 'application/vnd.ms-powerpoint'),
+    ('.pps', 'application/vnd.ms-powerpoint'),
+    ('.pot', 'application/vnd.ms-powerpoint'),
+    ('.pwz', 'application/vnd.ms-powerpoint'),
+    ('.eml',   'message/rfc822'),
+    ('.nws',   'message/rfc822'),
+    ('.mht',   'message/rfc822'),
+    ('.mhtml', 'message/rfc822'),
+    ('.css', 'text/css'),
+    ('.p7c', 'application/pkcs7-mime'),
+    ('.p12', 'application/x-pkcs12'),
+    ('.pfx', 'application/x-pkcs12'),
+    ('.js',  'application/x-javascript'),
+    ('.pct', 'image/pict'),
+    ('.pic', 'image/pict'),
+    ('.pict', 'image/pict'),
+    ('.m1v', 'video/mpeg'),
+    ('.mpa', 'video/mpeg'),
+    ('.vcf', 'text/x-vcard'),
+    ('.xml', 'text/xml'),
+    ('.xsl', 'text/xsl'),
+    ('.xul', 'text/xul'),
+    )
+for name, val in _addtypes:
+    mimetypes.types_map[name] = val
+
+def guess_content_type(name='', body='', default=None):
+    # Attempt to determine the content type (and possibly
+    # content-encoding) based on an an object's name and
+    # entity body.
+    type, enc = mimetypes.guess_type(name)
+    if type is None:
+        if body:
+            if find_binary(body) is not None:
+                type = default or 'application/octet-stream'
+            else:
+                type = (default or text_type(body)
+                      or 'text/x-unknown-content-type')
+        else:
+            type = default or 'text/x-unknown-content-type'
+
+    return type.lower(), enc and enc.lower() or None
+
+if __name__=='__main__':
+    items=mimetypes.types_map.items()
+    items.sort()
+    for item in items: print "%s:\t%s" % item


=== Zope3/src/zope/app/datetimeutils.py 1.1 => 1.2 === (889/989 lines abridged)
--- /dev/null	Wed Dec 25 09:13:56 2002
+++ Zope3/src/zope/app/datetimeutils.py	Wed Dec 25 09:12:24 2002
@@ -0,0 +1,986 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Commonly used utility functions.
+
+Encapsulation of date/time values
+
+$Id$
+"""
+
+__version__='$Revision$'[11:-2]
+
+import math
+import re
+import time as _time # there is a method definition that makes just "time"
+                     # problematic while executing a class definition
+
+from types import StringTypes
+
+try:
+    from time import tzname
+except ImportError:
+    tzname = ('UNKNOWN','UNKNOWN')
+
+# These are needed because the various date formats below must
+# be in english per the RFCs. That means we can't use strftime,
+# which is affected by different locale settings.
+weekday_abbr = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
+weekday_full = ['Monday', 'Tuesday', 'Wednesday', 'Thursday',
+                'Friday', 'Saturday', 'Sunday']
+monthname    = [None, 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
+                'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
+
+
+def iso8601_date(ts=None):
+    # Return an ISO 8601 formatted date string, required
+    # for certain DAV properties.

[-=- -=- -=- 889 lines omitted -=- -=- -=-]

+
+        if s.find('T')>-1:
+            fields = timereg.split(s[s.find('T')+1:])
+
+            if fields[1]:   hour     = int(fields[1])
+            if fields[3]:   minute   = int(fields[3])
+            if fields[5]:   seconds  = int(fields[5])
+            if fields[6]:   seconds  = seconds+float(fields[6])
+
+            if fields[8]:   tzsign   = fields[8]
+            if fields[9]:   hour_off = int(fields[9])
+            if fields[11]:  min_off  = int(fields[11])
+
+        return (year,month,day,hour,minute,seconds,
+                '%s%02d%02d' % (tzsign,hour_off,min_off))
+
+parser = DateTimeParser()
+parse = parser.parse
+time = parser.time
+
+from datetime import tzinfo as _tzinfo
+class tzinfo(_tzinfo):
+
+    __slots__ = ('offset', )
+
+    def __init__(self, offset):
+        self.offset = offset
+
+    def utcoffset(self, dt=None):
+        return self.offset
+
+    __getstate__ = utcoffset
+    __setstate__ = __init__
+
+    def dst(self, dt): return 0
+    def tzname(self, dt): return ''
+
+    def __repr__(self):
+        return 'tzinfo(%d)' % self.offset
+
+
+from datetime import datetimetz as _datetimetz
+def parseDatetimetz(string):
+    y, mo, d, h, m, s, tz = parse(string)
+    s, micro = divmod(s, 1.0)
+    micro = round(micro * 1000000)
+    offset = _tzoffset(tz, None) / 60
+    return _datetimetz(y, mo, d, h, m, s, micro, tzinfo(offset))
+
+_iso_tz_re = re.compile("[-+]\d\d:\d\d$")


=== Zope3/src/zope/app/dependable.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:56 2002
+++ Zope3/src/zope/app/dependable.py	Wed Dec 25 09:12:24 2002
@@ -0,0 +1,51 @@
+##############################################################################
+#
+# Copyright (c) 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$
+"""
+
+__metaclass__ = type
+
+from zope.app.interfaces.dependable import IDependable
+from zope.app.interfaces.annotation \
+     import IAnnotations
+from zope.component import getAdapter
+
+key = 'zope.app.dependable.Dependents'
+
+class Dependable:
+    __doc__ = IDependable.__doc__
+
+    __implements__ =  IDependable
+
+    def __init__(self, context):
+        self.context = context
+
+
+    def addDependent(self, location):
+        "See IDependable"
+        annotations = getAdapter(self.context, IAnnotations)
+        annotations [key] = annotations.get(key, ()) + (location, )
+
+    def removeDependent(self, location):
+        "See IDependable"
+        annotations = getAdapter(self.context, IAnnotations)
+        annotations[key] = tuple([loc
+                                  for loc in annotations.get(key, ())
+                                  if loc != location])
+
+    def dependents(self):
+        "See IDependable"
+        annotations = getAdapter(self.context, IAnnotations)
+        return annotations.get(key, ())


=== Zope3/src/zope/app/introspector.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:56 2002
+++ Zope3/src/zope/app/introspector.py	Wed Dec 25 09:12:24 2002
@@ -0,0 +1,151 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+
+from zope.interface import Interface
+from zope.interface.interfaces import IInterface
+from zope.interface.implements import implements, getImplements
+
+from zope.app.interfaces.introspector import IIntrospector
+from zope.app.interfaces.services.service import INameResolver
+from zope.component import getServiceManager, getAdapter, \
+     queryServiceManager, getServiceDefinitions
+from zope.proxy.introspection import removeAllProxies
+
+
+class Introspector:
+    """Introspects an object"""
+
+    __implements__ = IIntrospector
+
+    def __init__(self, context):
+        self.context = context
+        self.request = None
+        self.currentclass = None
+
+    def isInterface(self):
+        "Checks if the context is class or interface"
+        try:
+            ck = self.context.namesAndDescriptions()
+            return True
+        except:
+            return False
+
+    def setRequest(self, request):
+        """sets the request"""
+        self.request = request
+        if 'PATH_INFO' in request:
+            path = self.request['PATH_INFO']
+        else:
+            path = ''
+        name = path[path.rfind('++module++') + len('++module++'):]
+        name = name.split('/')[0]
+        if path.find('++module++') != -1:
+            if (self.context == Interface and
+                name != 'Interface._Interface.Interface'):
+                servicemanager = getServiceManager(self.context)
+                adapter = getAdapter(servicemanager, INameResolver)
+                self.currentclass = adapter.resolve(name)
+                self.context = self.currentclass
+            else:
+                self.currentclass = self.context
+        else:
+            self.currentclass = self.context.__class__
+
+    def _unpackTuple(self, tuple_obj):
+        res = []
+        for item in tuple_obj:
+            if type(item)==tuple:
+                res.extend(self._unpackTuple(item))
+            else:
+                res.append(item)
+        return tuple(res)
+
+    def getClass(self):
+        """Returns the class name"""
+        return (self.currentclass).__name__
+
+    def getBaseClassNames(self):
+        """Returns the names of the classes"""
+        bases = self.getExtends()
+        base_names = []
+        for base in bases:
+            base_names.append(base.__module__+'.'+base.__name__)
+        return base_names
+
+    def getModule(self):
+        """Returns the module name of the class"""
+        return (self.currentclass).__module__
+
+    def getDocString(self):
+        """Returns the description of the class"""
+        return removeAllProxies(self.currentclass).__doc__
+
+    def getInterfaces(self):
+        """Returns interfaces implemented by this class"""
+        interfaces = removeAllProxies(self.currentclass).__implements__
+        if type(interfaces) != tuple:
+            interfaces = (interfaces,)
+        else:
+            interfaces = self._unpackTuple(interfaces)
+        return interfaces
+
+    def getInterfaceNames(self):
+        names = []
+        try:
+            for intObj in self.getInterfaces():
+                names.append(intObj.__module__ + '.' + intObj.__name__)
+        except:
+            return []
+        else:
+            names.sort()
+            return names
+
+    def getInterfaceDetails(self):
+        """Returns the entire documentation in the interface"""
+        interface = self.context
+        Iname = interface.__name__
+        bases = []
+        desc = ''
+        methods = []
+        attributes = []
+        if interface is not None:
+            namesAndDescriptions = interface.namesAndDescriptions()
+            namesAndDescriptions.sort()
+            for name, desc in namesAndDescriptions:
+                if hasattr(desc, 'getSignatureString'):
+                    methods.append((desc.getName(),
+                                    desc.getSignatureString(),
+                                    desc.getDoc()))
+                else:
+                    attributes.append((desc.getName(), desc.getDoc()))
+
+            for base in interface.getBases():
+                bases.append(base.__module__+'.'+base.__name__)
+            desc = str(interface.__doc__)
+        return [Iname, bases, desc, methods, attributes]
+
+    def getExtends(self):
+        """Returns all the class extended up to the top most level"""
+        bases = self._unpackTuple((self.currentclass).__bases__)
+        return bases
+
+    def getInterfaceConfiguration(self):
+        """Returns details for a interface configuration"""
+        #sm = queryServiceManager(self.context)
+        service = []
+        for name, interface in getServiceDefinitions(self.context):
+            if self.context.extends(interface):
+                service.append(str(name))
+        print service
+        return service


=== Zope3/src/zope/app/meta.zcml 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:56 2002
+++ Zope3/src/zope/app/meta.zcml	Wed Dec 25 09:12:24 2002
@@ -0,0 +1,17 @@
+<zopeConfigure xmlns='http://namespaces.zope.org/zope'>
+
+<!-- Standard configuration directives -->
+<include package="zope.configuration" file="meta.zcml" />
+
+<include package="zope.app.component" file="meta.zcml" />
+<include package="zope.app.publisher" file="meta.zcml" />
+<include package="zope.app.traversing" file="meta.zcml" />
+<include package="zope.app.security" file="meta.zcml" />
+<include package="zope.app.browser.form" file="meta.zcml" />
+<include package="zope.app.contentdirective" file="meta.zcml" />
+<include package="zope.app.event" file="meta.zcml" />
+<include package="zope.app.i18n" file="meta.zcml" />
+<include package="zope.app.startup" file="meta.zcml" />
+<include package="zope.app.applicationcontrol" file="meta.zcml" />
+
+</zopeConfigure>


=== Zope3/src/zope/app/package_home.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:56 2002
+++ Zope3/src/zope/app/package_home.py	Wed Dec 25 09:12:24 2002
@@ -0,0 +1,23 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Function for deducing a package file-system location from global data
+
+$Id$
+"""
+
+import os
+
+def package_home(gdict):
+    filename = gdict["__file__"]
+    return os.path.dirname(filename)