[Zope3-checkins] CVS: Zope3/src/zodb/code - class_.py:1.1.2.1 module.py:1.1.2.2 patch.py:1.1.2.2 class.py:NONE
Tim Peters
tim.one@comcast.net
Mon, 23 Dec 2002 15:25:00 -0500
Update of /cvs-repository/Zope3/src/zodb/code
In directory cvs.zope.org:/tmp/cvs-serv1466/src/zodb/code
Modified Files:
Tag: NameGeddon-branch
module.py patch.py
Added Files:
Tag: NameGeddon-branch
class_.py
Removed Files:
Tag: NameGeddon-branch
class.py
Log Message:
Renamed class.py to class_.py, and fixed relevant imports.
=== Added File Zope3/src/zodb/code/class_.py ===
##############################################################################
#
# 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.
#
##############################################################################
"""Persistent Classes."""
from persistence import Persistent, PersistentMetaClass
from persistence.persistence import UPTODATE, CHANGED, STICKY, GHOST
from persistence.interfaces import IPersistent
from zodb.code.function import PersistentFunction
import new
from types import FunctionType as function
import time
# XXX There is a lot of magic here to give classes and instances
# separate sets of attributes. This code should be documented, as it
# it quite delicate, and it should be move to a separate module.
__metaclass__ = type
class ExtClassDescr:
"""Maintains seperate class and instance descriptors for an attribute.
This allows a class to provide methods and attributes without
intefering with normal use of instances. The class and its
instances can each have methods with the same name.
This does interfere with introspection on the class.
"""
def __init__(self, name, instdescr):
self.name = name
self.instdescr = instdescr
def __get__(self, obj, cls):
if obj is None:
return self.clsget(cls)
else:
return self.instdescr.__get__(obj, cls)
def __set__(self, obj, val):
if obj is None:
self.clsset(val)
else:
if self.instdescr is None:
raise AttributeError, self.name
return self.instdescr.__set__(obj, val)
def __delete__(self, obj):
if self.instdescr is None:
raise AttributeError, self.name
return self.instdescr.__delete__(obj)
# subclass should override
def clsget(self, cls):
pass
def clsset(self, val):
pass
def clsdelete(self):
pass
class MethodMixin:
def __init__(self, name, descr, func):
super(MethodMixin, self).__init__(name, descr)
self.func = func
def clsget(self, cls):
def f(*args, **kwargs):
try:
return self.func(cls, *args, **kwargs)
except TypeError:
print `self.func`, `cls`, `args`, `kwargs`
raise
return f
class DataMixin:
def __init__(self, name, descr, val):
super(DataMixin, self).__init__(name, descr)
self.val = val
def clsget(self, cls):
return self.val
def clsset(self, val):
self.val = val
def clsdelete(self):
del self.val
class ExtClassObject:
_missing = object()
def __init__(self, name, instdescr):
self.name = name
self.instdescr = instdescr
def __get__(self, obj, cls):
if obj is None:
return self.clsget(cls)
else:
return self.instdescr.__get__(obj, cls)
def __set__(self, obj, cls):
if obj is None:
return self.clsset(cls)
else:
if self.instdescr is None:
raise AttributeError, self.name
return self.instdescr.__set__(obj, cls)
def __delete__(self, obj, cls):
if obj is None:
return self.clsdelete(cls)
else:
if self.instdescr is None:
raise AttributeError, self.name
return self.instdescr.__delete__(obj, cls)
class ExtClassMethodDescr(MethodMixin, ExtClassDescr):
pass
class ExtClassDataDescr(DataMixin, ExtClassDescr):
pass
# The next three classes conspire to make a PersistentFunction
# behave like a method when found in a class's __dict__.
class PersistentMethod:
"""Make PersistentFunctions into methods."""
def __init__(self, klass, inst, func):
self.im_class = klass
self.im_self = inst
self.im_func = func
def __repr__(self):
if self.im_self is None:
kind = "unbound"
else:
kind = "bound"
return ("<persistent %s method %s.%s of %s>"
% (kind, self.im_class.__name__, self.im_func.__name__,
self.im_self))
def __call__(self, *args, **kwargs):
if self.im_self is None:
if not isinstance(args[0], self.im_class):
raise TypeError("unbound method %s() must be called "
"with %s instance as first argument ("
"got %s instead)" % (self.im_func.__name__,
self.im_class.__name__,
type(args[0]).__name__))
else:
return self.im_func(self.im_self, *args, **kwargs)
class PersistentDescriptor:
def __init__(self, objclass, func):
self.__name__ = func.__name__
self.__doc__ = func.__doc__
self.__objclass__ = objclass
self._func = func
# Delegate __getstate__ and __setstate__ to the persistent func.
# The patch module will use these methods to update persistent
# methods in place.
self.__getstate__ = func.__getstate__
self.__setstate__ = func.__setstate__
def __repr__(self):
return "<descriptor %s.%s>" % (self.__objclass__.__name__,
self.__name__)
def __get__(self, object, klass=None):
if object is None:
return PersistentMethod(klass or self.__objclass__, None,
self._func)
else:
return PersistentMethod(klass or self.__objclass__, object,
self._func)
# XXX is missing necessary for findattr?
# None might be sufficient
_missing = object()
def findattr(cls, attr, default):
"""Walk the mro of cls to find attr."""
for c in cls.__mro__:
o = c.__dict__.get(attr, _missing)
if o is not _missing:
return o
return default
class PersistentClassMetaClass(PersistentMetaClass):
# an attempt to make persistent classes look just like other
# persistent objects by providing class attributes and methods
# that behave like the persistence machinery.
# the chief limitation of this approach is that class.attr won't
# always behave the way it does for normal classes
__implements__ = IPersistent
_pc_init = False
def __new__(meta, name, bases, dict):
cls = super(PersistentClassMetaClass, meta).__new__(
meta, name, bases, dict)
# helper functions
def extend_attr(attr, v):
prev = findattr(cls, attr, None)
setattr(cls, attr, ExtClassDataDescr(attr, prev, v))
def extend_meth(attr, m):
prev = findattr(cls, attr, None)
setattr(cls, attr, ExtClassMethodDescr(attr, prev, m))
extend_attr("_p_oid", None)
extend_attr("_p_jar", None)
extend_attr("_p_state", UPTODATE)
extend_meth("_p_activate", meta._p_activate)
extend_meth("_p_deactivate", meta._p_activate)
extend_meth("__getstate__", meta.__getstate__)
extend_meth("__setstate__", meta.__setstate__)
extend_attr("__implements__", meta.__implements__)
for k, v in dict.items():
if isinstance(v, PersistentFunction):
setattr(cls, k, PersistentDescriptor(cls, v))
cls._pc_init = True
return cls
def fixup(cls, mod):
for k, v in cls.__dict__.items():
if isinstance(v, function):
setattr(cls, k, PersistentFunction(v, mod))
def __getattribute__(cls, name):
# XXX I'm not sure I understand this code any more.
super_meth = super(PersistentClassMetaClass, cls).__getattribute__
# If we are initializing the class, don't trying to check variables
# like _p_state, since they may not be initialized.
if not super_meth("_pc_init"):
return super_meth(name)
if (name[0] == "_" and
not (name.startswith("_p_") or name.startswith("_pc_") or
name == "__dict__")):
if cls._p_state == GHOST:
cls._p_activate()
cls._p_atime = int(time.time() % 86400)
return super_meth(name)
def __setattr__(cls, attr, val):
if not attr.startswith("_pc_") and cls._pc_init:
descr = cls.__dict__.get(attr)
if descr is not None:
set = getattr(descr, "__set__", None)
if set is not None:
set(None, val)
return
super(PersistentClassMetaClass, cls).__setattr__(attr, val)
def __delattr__(cls, attr):
if attr.startswith('_p_'):
if attr == "_p_changed":
# this means something special
pass
else:
return
super(PersistentClassMetaClass, cls).__delattr__(attr)
def __getstate__(cls):
dict = {}
for k, v in cls.__dict__.items():
if hasattr(v, '_p_oid'):
dict[k] = v
return dict
def __setstate__(cls, dict):
for k, v in dict.items():
setattr(cls, k, v)
def _p_deactivate(cls):
# do nothing but mark the state change for now
cls._p_state = GHOST
def _p_activate(cls):
if cls._p_state is None:
dm = cls._p_jar
if dm is not None:
# reactivate
cls._p_state = UPTODATE
# Methods below here are not wrapped to be class-only attributes.
# They are available as methods of classes using this metaclass.
def __getnewargs__(cls):
return cls.__name__, cls.__bases__, {}
def _p_newstate(cls, acls):
# Update a class's __dict__ in place. Must use setattr and
# delattr because __dict__ is a read-only proxy.
# XXX This doesn't handle __methods__ correctly.
def getkeys(cls):
L = [n for n in cls.__dict__.keys()
if not (n.startswith("__") and n.endswith("__"))]
d = {}
for elt in L:
d[elt] = True
return d
oldnames = getkeys(cls)
newnames = getkeys(acls)
for name in oldnames:
if not name in newnames:
delattr(cls, name)
for name in newnames:
setattr(cls, name, acls.__dict__[name])
=== Zope3/src/zodb/code/module.py 1.1.2.1 => 1.1.2.2 ===
--- Zope3/src/zodb/code/module.py:1.1.2.1 Mon Dec 23 14:30:48 2002
+++ Zope3/src/zodb/code/module.py Mon Dec 23 15:24:59 2002
@@ -22,7 +22,7 @@
from persistence import Persistent
from persistence.persistence import GHOST
-from zodb.code.class import PersistentClassMetaClass
+from zodb.code.class_ import PersistentClassMetaClass
from zodb.code.function import PersistentFunction
from zodb.code.interfaces import IPersistentModuleManager
from zodb.code.interfaces \
=== Zope3/src/zodb/code/patch.py 1.1.2.1 => 1.1.2.2 ===
--- Zope3/src/zodb/code/patch.py:1.1.2.1 Mon Dec 23 14:30:48 2002
+++ Zope3/src/zodb/code/patch.py Mon Dec 23 15:24:59 2002
@@ -82,7 +82,7 @@
import pickle
from types import *
-from zodb.code.class import PersistentClassMetaClass, PersistentDescriptor
+from zodb.code.class_ import PersistentClassMetaClass, PersistentDescriptor
from zodb.code.function import PersistentFunction
from persistence import Persistent
=== Removed File Zope3/src/zodb/code/class.py ===