Commit b4d37a31 authored by 's avatar

- removed metaclass (AFAICS it is obsolete)

parent 3aea68c0
...@@ -73,6 +73,8 @@ Features Added ...@@ -73,6 +73,8 @@ Features Added
Restructuring Restructuring
+++++++++++++ +++++++++++++
- Five: Removed obsolete metaclass.
- Five: Refactored ``browser:view`` and ``browser:page`` directives. - Five: Refactored ``browser:view`` and ``browser:page`` directives.
This makes their implementation more similar to that in ``zope.browserpage`` This makes their implementation more similar to that in ``zope.browserpage``
and adds allowed_interface support for the ``browser:view`` directive. and adds allowed_interface support for the ``browser:view`` directive.
......
...@@ -8,9 +8,5 @@ Five contains source code derived from: ...@@ -8,9 +8,5 @@ Five contains source code derived from:
- Zope, copyright (C) 2001-2005 by Zope Corporation. - Zope, copyright (C) 2001-2005 by Zope Corporation.
- metaclass.py is derived from PEAK, copyright (C) 1996-2004 by
Phillip J. Eby and Tyler C. Sarna. PEAK may be used under the same
terms as Zope.
- TrustedExecutables. Dieter Mauer kindly allow licensing this under the - TrustedExecutables. Dieter Mauer kindly allow licensing this under the
ZPL 2.1. ZPL 2.1.
...@@ -51,7 +51,6 @@ from Products.Five.browser.resource import ImageResourceFactory ...@@ -51,7 +51,6 @@ from Products.Five.browser.resource import ImageResourceFactory
from Products.Five.browser.resource import PageTemplateResourceFactory from Products.Five.browser.resource import PageTemplateResourceFactory
from Products.Five.browser.resource import DirectoryResourceFactory from Products.Five.browser.resource import DirectoryResourceFactory
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from Products.Five.metaclass import makeClass
def _configure_z2security(_context, new_class, required): def _configure_z2security(_context, new_class, required):
_context.action( _context.action(
...@@ -131,7 +130,7 @@ def page(_context, name, permission, for_=Interface, ...@@ -131,7 +130,7 @@ def page(_context, name, permission, for_=Interface,
}) })
cdict['__name__'] = name cdict['__name__'] = name
cdict['__page_attribute__'] = attribute cdict['__page_attribute__'] = attribute
new_class = makeClass(class_.__name__, (class_, simple), cdict) new_class = type(class_.__name__, (class_, simple,), cdict)
if attribute != "__call__": if attribute != "__call__":
# in case the attribute does not provide a docstring, # in case the attribute does not provide a docstring,
...@@ -273,7 +272,7 @@ class view(zope.browserpage.metaconfigure.view): ...@@ -273,7 +272,7 @@ class view(zope.browserpage.metaconfigure.view):
cname = "GeneratedClass" cname = "GeneratedClass"
cdict['__name__'] = name cdict['__name__'] = name
newclass = makeClass(cname, bases, cdict) newclass = type(cname, bases, cdict)
for n in ('',): for n in ('',):
required[n] = permission required[n] = permission
...@@ -331,7 +330,7 @@ def resource(_context, name, layer=IDefaultBrowserLayer, permission='zope.Public ...@@ -331,7 +330,7 @@ def resource(_context, name, layer=IDefaultBrowserLayer, permission='zope.Public
factory_info['count'] += 1 factory_info['count'] += 1
res_factory = factory_info['factory'] res_factory = factory_info['factory']
class_name = '%s%s' % (factory_info['prefix'], factory_info['count']) class_name = '%s%s' % (factory_info['prefix'], factory_info['count'])
new_class = makeClass(class_name, (res_factory.resource,), {}) new_class = type(class_name, (res_factory.resource,), {})
factory = res_factory(name, res, resource_factory=new_class) factory = res_factory(name, res, resource_factory=new_class)
_context.action( _context.action(
...@@ -380,9 +379,9 @@ def resourceDirectory(_context, name, directory, layer=IDefaultBrowserLayer, ...@@ -380,9 +379,9 @@ def resourceDirectory(_context, name, directory, layer=IDefaultBrowserLayer,
factory_info['count'] += 1 factory_info['count'] += 1
class_name = '%s%s' % (factory_info['prefix'], factory_info['count']) class_name = '%s%s' % (factory_info['prefix'], factory_info['count'])
factory_name = '%s%s' % (factory.__name__, factory_info['count']) factory_name = '%s%s' % (factory.__name__, factory_info['count'])
f_resource = makeClass(class_name, (factory.resource,), {}) f_resource = type(class_name, (factory.resource,), {})
f_cache[factory] = makeClass(factory_name, (factory,), f_cache[factory] = type(factory_name, (factory,),
{'resource':f_resource}) {'resource': f_resource})
for ext, factory in resource_factories.items(): for ext, factory in resource_factories.items():
resource_factories[ext] = f_cache[factory] resource_factories[ext] = f_cache[factory]
default_factory = resource_factories['default'] default_factory = resource_factories['default']
...@@ -394,7 +393,7 @@ def resourceDirectory(_context, name, directory, layer=IDefaultBrowserLayer, ...@@ -394,7 +393,7 @@ def resourceDirectory(_context, name, directory, layer=IDefaultBrowserLayer,
factory_info = _rd_map.get(DirectoryResourceFactory) factory_info = _rd_map.get(DirectoryResourceFactory)
factory_info['count'] += 1 factory_info['count'] += 1
class_name = '%s%s' % (factory_info['prefix'], factory_info['count']) class_name = '%s%s' % (factory_info['prefix'], factory_info['count'])
dir_factory = makeClass(class_name, (resource,), cdict) dir_factory = type(class_name, (resource,), cdict)
factory = DirectoryResourceFactory(name, directory, factory = DirectoryResourceFactory(name, directory,
resource_factory=dir_factory) resource_factory=dir_factory)
...@@ -454,7 +453,7 @@ def SimpleViewClass(src, offering=None, used_for=None, bases=(), name=u''): ...@@ -454,7 +453,7 @@ def SimpleViewClass(src, offering=None, used_for=None, bases=(), name=u''):
bases += (ViewMixinForTemplates,) bases += (ViewMixinForTemplates,)
class_ = makeClass("SimpleViewClass from %s" % src, bases, cdict) class_ = type("SimpleViewClass from %s" % src, bases, cdict)
if used_for is not None: if used_for is not None:
class_.__used_for__ = used_for class_.__used_for__ = used_for
......
...@@ -21,7 +21,7 @@ views still works (the printed output is the aq_chain of the view): ...@@ -21,7 +21,7 @@ views still works (the printed output is the aq_chain of the view):
>>> browser.open('http://localhost/test_folder_1_/attributes') >>> browser.open('http://localhost/test_folder_1_/attributes')
>>> print browser.contents >>> print browser.contents
[<Products.Five.metaclass.LegacyAttributes object at ...>, [<Products.Five.browser.metaconfigure.LegacyAttributes object at ...>,
<Folder at /test_folder_1_>, <Folder at /test_folder_1_>,
<Application at >, <Application at >,
<ZPublisher.BaseRequest.RequestContainer object at ...>] <ZPublisher.BaseRequest.RequestContainer object at ...>]
...@@ -30,7 +30,7 @@ The same goes for browser views that just mix in Acquisition.Explicit: ...@@ -30,7 +30,7 @@ The same goes for browser views that just mix in Acquisition.Explicit:
>>> browser.open('http://localhost/test_folder_1_/explicitattributes') >>> browser.open('http://localhost/test_folder_1_/explicitattributes')
>>> print browser.contents >>> print browser.contents
[<Products.Five.metaclass.ExplicitLegacyAttributes object at ...>, [<Products.Five.browser.metaconfigure.ExplicitLegacyAttributes object at ...>,
<Folder at /test_folder_1_>, <Folder at /test_folder_1_>,
<Application at >, <Application at >,
<ZPublisher.BaseRequest.RequestContainer object at ...>] <ZPublisher.BaseRequest.RequestContainer object at ...>]
......
...@@ -77,14 +77,14 @@ it shouldn't modify existing ones: ...@@ -77,14 +77,14 @@ it shouldn't modify existing ones:
Make sure new-style classes work fine as view classes: Make sure new-style classes work fine as view classes:
>>> self.folder.unrestrictedTraverse('testoid/@@new_style_class') >>> self.folder.unrestrictedTraverse('testoid/@@new_style_class')
<Products.Five.metaclass.NewStyleClass ...> <Products.Five.browser.metaconfigure.NewStyleClass ...>
At one point browser classes with no attribute and no template At one point browser classes with no attribute and no template
values specified wasn't getting BrowserView mixed in. Lets make values specified wasn't getting BrowserView mixed in. Lets make
sure it is now: sure it is now:
>>> self.folder.unrestrictedTraverse('testoid/@@new_style_class2') >>> self.folder.unrestrictedTraverse('testoid/@@new_style_class2')
<Products.Five.metaclass.NewStyleClass ...> <Products.Five.browser.metaconfigure.NewStyleClass ...>
Both browser:view and browser:page are ILocation providers, so make sure they Both browser:view and browser:page are ILocation providers, so make sure they
have a __name__ attribute: have a __name__ attribute:
......
##############################################################################
#
# Copyright (c) 2004, 2005 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (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.
#
##############################################################################
# metaclass taken from PEAK.
# Martijn doesn't pretend to understand this.
from weakref import WeakValueDictionary
from types import ClassType
def makeClass(name,bases,dict):
"""makeClass(name, bases, dict) - enhanced class creation
"""
# Create either a "classic" Python class, an ExtensionClass, or a new-style
# class with autogenerated metaclass, based on the nature of the base
# classes involved
name = str(name) # De-unicode
metaclasses = [getattr(b,'__class__',type(b)) for b in bases]
if dict.has_key('__metaclass__'):
metaclasses.insert(0,dict['__metaclass__'])
if dict.has_key('__metaclasses__'):
metaclasses[0:0] = list(dict['__metaclasses__'])
metaclasses = normalizeBases(metaclasses)
if metaclasses:
# If we have metaclasses, it's not a classic class, so derive a
# single metaclass, and ask it to create the class.
if len(metaclasses)==1:
metaclass = metaclasses[0]
else:
metaclass = derivedMeta(metaclasses)
return metaclass(name,bases,dict)
# No metaclasses, it's a classic class, so use 'new.classobj'
from new import classobj; return classobj(name,bases,dict)
def normalizeBases(allBases):
return minimalBases([b for b in allBases if b is not makeClass])
def minimalBases(classes):
"""Reduce a list of base classes to its ordered minimum equivalent"""
classes = [c for c in classes if c is not ClassType]
candidates = []
for m in classes:
for n in classes:
if issubclass(n,m) and m is not n:
break
else:
# m has no subclasses in 'classes'
if m in candidates:
candidates.remove(m) # ensure that we're later in the list
candidates.append(m)
return candidates
metaReg = WeakValueDictionary()
def derivedMeta(metaclasses):
metaclasses = tuple(metaclasses)
derived = metaReg.get(metaclasses)
if derived is None:
normalized = tuple(normalizeBases(metaclasses))
derived = metaReg.get(normalized)
if derived is None:
if len(normalized)==1:
derived = normalized[0]
else:
derived = metaFromBases(normalized)(
'_'.join([n.__name__ for n in normalized]),
metaclasses, {}
)
try: metaReg[normalized] = derived
except TypeError: pass # Some metatypes can't be weakref'd
try: metaReg[metaclasses] = derived
except TypeError: pass
return derived
def metaFromBases(bases):
meta = tuple([getattr(b,'__class__',type(b)) for b in bases])
if meta==bases: raise TypeError("Incompatible root metatypes",bases)
return derivedMeta(meta)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment