示例#1
0
class SMTPFactory(binding.Singleton):

    protocols.advise(classProvides=[naming.IObjectFactory])

    def getObjectInstance(self, context, refInfo, name, attrs=None):
        addr, = refInfo.addresses
        addr = adapt(addr, smtpURL)
        return smtplib.SMTP(addr.host, addr.port)
示例#2
0
class _StringAsRecipe(_TypeAsRecipe):
    """ADAPTER: string (import spec) --> IRecipe"""

    protocols.advise(instancesProvide=[IRecipe], asAdapterForTypes=[str])

    def __call__(self, component, instDict, attrName):
        return adapt(importString(self.subject), IRecipe)(component, instDict,
                                                          attrName)

    def __repr__(self):
        return self.subject
示例#3
0
class _TypeAsRecipe:
    """ADAPTER: type | class --> IRecipe"""

    protocols.advise(instancesProvide=[IRecipe],
                     asAdapterForTypes=[type, ClassType])

    def __init__(self, ob):
        self.subject = ob
        self.__doc__ = None  # Don't use the type's docstring as our docstring

    def __call__(self, component, instDict, attrName):
        return self.subject()

    def __repr__(self):
        return "%s.%s" % (self.subject.__module__, self.subject.__name__)
示例#4
0
class _MultiRecipe:
    """ADAPTER: Sequence(IRecipe) --> IRecipe"""

    protocols.advise(instancesProvide=[IRecipe],
                     asAdapterForProtocols=[protocols.sequenceOf(IRecipe)])

    def __init__(self, ob):
        self.subject = ob
        self.__doc__ = getattr(ob, '__doc__', None)

    def __repr__(self):
        return repr(self.subject)

    def __call__(self, component, instDict, attrName):
        return tuple(
            [ob(component, instDict, attrName) for ob in self.subject])
示例#5
0
class LockFileBase:
    """Common base for lockfiles"""

    protocols.advise(instancesProvide=[ILock],
                     classProvides=[naming.IObjectFactory])

    def __init__(self, fn):
        self.fn = os.path.abspath(fn)
        self._lock = allocate_lock()
        self._locked = False

    def attempt(self):
        if self._lock.acquire(False):
            r = False
            try:
                r = self.do_acquire(False)
            finally:
                if not r and self._lock.locked():
                    self._lock.release()
            return r
        else:
            return False

    def obtain(self):
        self._lock.acquire()
        r = False
        try:
            r = self.do_acquire(True)
        finally:
            if not r and self._lock.locked():
                self._lock.release()
        if not r:
            raise RuntimeError, "lock obtain shouldn't fail!"

    def release(self):
        self.do_release()
        self._locked = False
        self._lock.release()

    def locked(self):
        return self._locked

    def getObjectInstance(klass, context, refInfo, name, attrs=None):
        url, = refInfo.addresses
        return klass(url.getFilename())

    getObjectInstance = classmethod(getObjectInstance)
示例#6
0
class ActiveClass(Activator):
    """Metaclass for classes that are themselves components"""

    protocols.advise(instancesProvide=[IActiveDescriptor])

    def activateInClass(self, klass, attrName):

        if klass.__module__ == self.__module__:

            if '__parent__' not in self.__dict__ and attrName != '__metaclass__':
                # We use a tuple, so that if our parent is a descriptor,
                # it won't interfere when our instance tries to set *its*
                # parent!
                self.__parent__ = klass,

        return self

    def __parent__(self, d, a):

        parent = self.__module__
        name = self.__name__

        if '.' in name:
            name = '.'.join(name.split('.')[:-1])
            parent = '%s:%s' % (parent, name)

        return importString(parent),

    __parent__ = Make(__parent__, suggestParent=False)

    def __cname__(self, d, a):
        return self.__name__.split('.')[-1]

    __cname__ = Make(__cname__, suggestParent=False)

    def __all_descriptors__(klass):
        ad = {}
        map(ad.update, getInheritedRegistries(klass, '__all_descriptors__'))
        ad.update(klass.__class_descriptors__)
        return ad

    __all_descriptors__ = Make(__all_descriptors__, suggestParent=False)
示例#7
0
class FacadeDM(binding.Component):

    """DM that just returns objects from other DM(s) via a different key"""

    protocols.advise(
        instancesProvide=[IKeyableDM]
    )

    def __getitem__(self, oid, state=None):

        ob = self.cache.get(oid,self)

        if ob is not self:

            # double-check identity
            if oid==self.oidFor(ob):
                return ob

            # Oops, key no longer valid, drop it
            del self.cache[oid]

        ob = self._retrieve(oid, state)

        if ob is not None:
            self.cache[oid] = ob
            return ob

        raise KeyError, oid

    preloadState = __getitem__

    cache = binding.Make('peak.storage.caches:WeakCache')

    def _retrieve(self, oid, state=None):
        """Look up 'oid' in underlying storage and return it, or 'None'"""
        raise NotImplementedError

    def oidFor(self, ob):
        """Return this DM's OID for 'ob'; used to validate consistency"""
        raise NotImplementedError
示例#8
0
class EntityDM(QueryDM):

    protocols.advise(
        instancesProvide=[IWritableDM]
    )

    def oidFor(self, ob):

        if ob._p_jar is self:

            oid = ob._p_oid

            if oid is None:
                # force it to have an ID by saving it
                ob._p_changed = 1
                self.flush(ob)
                return ob._p_oid

            else:
                return oid

        else:
            return self._thunk(ob)


    def newItem(self,klass=None):

        if klass is None:
            klass = self.defaultClass

        if klass is None:
            raise NotImplementedError

        ob=klass()
        ob.__setstate__(self._defaultState(ob))

        self.add(ob)
        return ob



    # Set/state management

    dirty = binding.Make(dict)
    saved = binding.Make(dict)
    to_delete = binding.Make(list)

    def flush(self, ob=None):

        markSaved = self.saved.setdefault
        dirty = self.dirty
        orig_ob = ob

        if ob is None:
            obs = dirty.values()
        else:
            obs = [ob]

        for ob in obs:

            if ob._p_oid is None:

                # No oid, it's a new object that needs saving
                oid = ob._p_oid = self._new(ob)
                self.cache[oid]=ob

            else:
                # just save it the ordinary way
                self._save(ob)

            # Update status flags and object sets
            key = id(ob)
            markSaved(key,ob)
            if key in dirty:
                del dirty[key]
            ob._p_changed = False

        if orig_ob is None and self.to_delete:
            self._delete_oids(self.to_delete)
            del self.to_delete


    # Private abstract methods/attrs

    defaultClass = None

    def _save(self, ob):
        raise NotImplementedError

    def _new(self, ob):
        raise NotImplementedError

    def _defaultState(self, ob):
        return ob.__getstate__()

    def _thunk(self, ob):
        raise NotImplementedError

    def _delete_oids(self,oidList):
        raise NotImplementedError

    def _check(self,ob):
        """Override this to raise an error if 'ob' is unsuitable for storing"""

    # Persistence.IPersistentDataManager methods

    def register(self, ob):
        # Ensure that we have a transaction service and we've joined
        # the transaction in progress...
        self.joinedTxn

        # precondition:
        #   object has been changed since last save
        # postcondition:
        #   ob is in 'dirty' set
        #   DM is registered w/transaction if not previously registered
        key = id(ob)

        # Ensure it's in the 'dirty' set
        self.dirty.setdefault(key,ob)

        return self.joinedTxn

    # ITransactionParticipant methods

    def readyToVote(self, txnService):
        if self.dirty or self.to_delete:
            self.flush()
            return False
        else:
            return True


    def voteForCommit(self, txnService):
        # Everything should have been written by now...  If not, it's VERY BAD
        # because the DB we're storing to might've already gotten a tpc_vote(),
        # and won't accept writes any more.  So raise holy hell if we're dirty!
        assert not self.dirty and not self.to_delete


    def commitTransaction(self, txnService):
        self.saved.clear()
        self._delBinding('to_delete')


    def abortTransaction(self, txnService):

        for ob in self.dirty.values():
            ob._p_changed = False
            ob._p_deactivate()

        self.dirty.clear()

        for ob in self.saved.values():
            if ob._p_jar is self:   # don't deactivate formerly-owned objects               
                ob._p_deactivate()

        self.saved.clear()
        self._delBinding('to_delete')





    def add(self,ob):
        if not isinstance(ob,Persistent):
            raise TypeError("Not a persistent object", ob)

        if ob._p_jar is self:
            return  # Nothing needed here
        elif ob._p_jar is not None:
            raise ValueError("Already in another DM", ob, ob._p_jar)

        self._check(ob)
        if ob._p_oid is not None:
            if self.get(ob._p_oid) is not None:
                raise InvalidKeyError("Duplicate key", ob._p_oid)
            self.cache[ob._p_oid] = ob

        ob._p_jar = self
        self.register(ob)


    def remove(self,ob):
        if ob._p_jar is not self:
            raise ValueError("Doesn't belong to this DM", ob, ob._p_jar)

        key = id(ob)
        if key in self.dirty:
            del self.dirty[key]

        # note: don't delete from 'saved', because we might still need to roll
        # back the object's state if it gets re-added, but the txn aborts, and
        # we don't have 'resetStatesAfterTxn' set.

        del self.cache[ob._p_oid]
        ob._p_jar = None

        self.to_delete.append(ob._p_oid)

        # Ensure that we have a transaction service and we've joined
        # the transaction in progress...
        self.joinedTxn
示例#9
0
class QueryDM(TransactionComponent):

    resetStatesAfterTxn = True

    protocols.advise(
        instancesProvide=[IDataManager]
    )

    to_delete = ()

    def __getitem__(self, oid, state=None):

        if self.resetStatesAfterTxn:
            # must always be used in a txn
            self.joinedTxn

        if oid in self.to_delete:
            raise InvalidKeyError("Reference to deleted key", oid)

        ob = self.cache.get(oid,self)

        if ob is not self:
            return ob

        ob = self._ghost(oid,state)

        if isinstance(ob,Persistent):

            ob._p_jar = self
            ob._p_oid = oid

            if state is None:
                ob._p_deactivate()
            else:
                ob.__setstate__(state)

        self.cache[oid] = ob
        return ob

    preloadState = __getitem__

    # Private abstract methods/attrs

    cache = binding.Make('peak.storage.caches:WeakCache')

    defaultClass = PersistentQuery

    def _ghost(self, oid, state=None):

        klass = self.defaultClass

        if klass is None:
            raise NotImplementedError

        return klass()


    def _load(self, oid, ob):
        raise NotImplementedError


    # Persistence.IPersistentDataManager methods

    def setstate(self, ob):

        if self.resetStatesAfterTxn:
            # must always be used in a txn
            self.joinedTxn

        oid = ob._p_oid
        assert oid is not None
        ob.__setstate__(self._load(oid,ob))


    def mtime(self, ob):
        pass    # return None

    def register(self, ob):
        raise TypeError("Attempt to modify query result", ob)



    # ITransactionParticipant methods

    def finishTransaction(self, txnService, committed):

        if self.resetStatesAfterTxn:

            for oid, ob in self.cache.items():
                if isinstance(ob,Persistent):
                    ob._p_deactivate()

        super(QueryDM,self).finishTransaction(txnService,committed)

    # Misc.

    def __iter__(self):
        raise NotImplementedError


    def __contains__(self, ob):
        if isinstance(ob,Persistent):
            return ob._p_jar is self
        return self.get(ob) is not None


    def get(self,oid,default=None):
        if self.resetStatesAfterTxn:
            # must always be used in a txn
            self.joinedTxn

        if oid in self.cache:
            return self.cache[oid]
        elif oid in self.to_delete:
            return default
        try:
            state = self._load(oid,None)
        except InvalidKeyError:
            return default
        else:
            return self.preloadState(oid,state)
示例#10
0
    of on framework-oriented concerns.
"""

from peak.util.imports import importObject
from peak.api import adapt, protocols
from interfaces import *
from names import NNS_Reference

from peak.binding.interfaces import IComponentFactory

__all__ = [
    'getInitialContext',
    'getURLContext',
]

protocols.advise(moduleProvides=[IURLContextFactory, IInitialContextFactory])


def getInitialContext(parentComponent, componentName=None, **options):
    """Create initial context for parent, w/component name and options

    The type of initial context created is determined by asking the supplied
    'parentComponent' for its 'peak.naming.initialContextFactory' property,
    which will be treated as an import string if it is of string type.
    (Note: the property name used is available as the constant
    'naming.INIT_CTX_FACTORY', if you want to provide an attribute binding
    for it.)

    Keyword options and the component name desired for the initial context
    are passed through to the actual factory, along with the parent component
    and component name.  If a 'creationParent' argument is not supplied,
示例#11
0
class CacheBase(binding.Component):
    protocols.advise(instancesProvide=[ICache])
示例#12
0
class Attribute(Descriptor):
    """Descriptor for Component Attribute Bindings

    'Attribute' is a 'Descriptor' with additional features to make component
    interconnection easier.  Specifically, 'Attribute' adds the ability to
    automatically adapt computed or assigned values to a specific interface,
    and the ability to automatically "suggest" to an assigned value that the
    containing object should become its parent component.  In addition,
    'Attribute' has various metadata attributes that can be read by a
    containing class, to enable various features such as "offering" the
    attribute as a supplier of a particular interface or configuration key.

    In addition, if an 'Attribute' is placed in a 'binding.Component' subclass
    (or any class whose metaclass derives from 'binding.Activator'), it will
    automatically discover its 'attrName' from the class, so that you don't
    have to explicitly supply it.

    'Attribute' is primarily an abstract base class; you will ordinarily use
    'Make', 'Obtain', 'Require', or 'Delegate' instead.  However, all of those
    subclasses accept the same keyword arguments, and have the same basic
    lazy initialization and caching behavior.  They differ only in *how* they
    compute the attribute value, and in their constructors' positional arguments.

    In addition to the attributes defined by the 'Descriptor' base class,
    'Attribute' instances also have the following attributes, which may be
    overridden in subclasses, or by supplying constructor keyword arguments:

        'offerAs' -- A sequence of configuration keys under which the attribute
        should be registered.  This tells the containing 'Component' class
        to offer the attribute's value to child components when they look up
        any of the specified configuration keys.  Values in the supplied
        sequence will be adapted to the 'config.IConfigKey' interface.  Default
        value: an empty list.  (Note that this attribute has no effect unless
        the 'Attribute' is placed in a 'binding.Component' subclass.)

        'uponAssembly' -- A flag indicating whether the attribute should be
        initialized as soon as its containing component is part of a complete
        component hierarchy.  Default value: False.  (Note that this attribute
        has no effect unless the 'Attribute' is placed in a 'binding.Component'
        subclass.)

        'doc' -- A docstring, used to give an appropriate representation of the
        attribute when it's rendered by 'pydoc' or the Python 'help()'
        function.

        'adaptTo' -- the interface that values of this attribute should be
        adapted to, or 'None'.  If not 'None', then whenever the attribute is
        set (or its 'computeValue()' result is cached), the value will be
        adapted to this interface before being stored.  If adaptation fails,
        a 'NotImplementedError' will be raised.  (Note that this behavior is
        implemented by 'Attribute.onSet()'; if you override the default
        'onSet()', this adaptation will not take place unless your replacement
        does it.)

        'suggestParent' -- should assigned values be informed that they are
        being attached to the containing component?  This value defaults to
        'True', so you should set it to 'False' if you do not want the
        attachment to happen.  If 'True', then whenever the attribute is set
        (or its 'computeValue()' result is cached), 'suggestParentComponent()'
        will be called to let the value know that the containing component may
        be the value's parent component, and what attribute name it is being
        referenced by.  Note that this call happens *after* the value is first
        adapted to the 'adaptTo' interface, if applicable, and is also
        performed by 'Attribute.onSet()', so the same warning about overriding
        'onSet()' applies here.
    """

    __metaclass__ = AttributeClass

    protocols.advise(instancesProvide=[IActiveDescriptor])

    # XXX Set up 'activateUponAssembly' to set the 'uponAssembly' attribute
    # XXX This is for backward compatibility only, and should go away in a4

    activateUponAssembly = Descriptor(
        attrName='activateUponAssembly',
        onSet=lambda o, a, v: setattr(o, 'uponAssembly', v and 1 or 0) or v,
        computeValue=lambda o, d, a: False)

    offerAs = ()
    uponAssembly = False
    doc = None
    adaptTo = None
    suggestParent = True
    metadata = None

    def activateInClass(self, klass, attrName):
        setattr(klass, attrName, self._copyWithName(attrName))
        declareAttribute(klass, attrName, self.metadata)
        declareAttribute(klass, attrName, self.permissionNeeded)  # XXX
        return self

    def _copyWithName(self, attrName):
        return Descriptor(attrName=attrName,
                          computeValue=self.computeValue,
                          ofClass=self.ofClass,
                          onSet=self.onSet,
                          noCache=self.noCache,
                          permissionNeeded=self.permissionNeeded)

    def __repr__(self):
        if self.__doc__:
            return "binding.Attribute:\n\n%s" % self.__doc__
        else:
            return "binding.Attribute()"

    def onSet(self, obj, attrName, value):

        if self.adaptTo is not None:
            value = adapt(value, self.adaptTo)

        if self.suggestParent:
            suggestParentComponent(obj, attrName, value)
        return value

    # The following methods only get called when an instance of this class is
    # used as a descriptor in a classic class or other class that doesn't
    # support active descriptors.  So, we will use the invocation of these
    # methods to bootstrap our activation.  Once activated, these methods won't
    # be called any more.

    def __get__(self, ob, typ=None):
        if ob is None:
            return self
        return self._installedDescr(ob.__class__).__get__(ob, typ)

    def __set__(self, ob, value):
        self._installedDescr(ob.__class__).__set__(ob, value)

    def __delete__(self, ob, value):
        self._installedDescr(ob.__class__).__delete__(ob)

    def _installedDescr(self, klass):
        # Return a newly installed descriptor proxy to use, or raise a usage
        # error if self doesn't know its own right name.

        from protocols.advice import getMRO
        name = self.attrName

        for cls in getMRO(klass):
            if name in cls.__dict__:
                if cls.__dict__[name] is self:
                    # Install a proxy, so we don't have to do this again!
                    descr = self._copyWithName(name)
                    setattr(cls, name, descr)
                    return descr
                else:
                    break

        # If we get here, we were not found under the name we were given
        self.usageError()
示例#13
0
class Base(Struct):
    """Basic scheme/body URL"""

    protocols.advise(instancesProvide=[IAddress],
                     classProvides=[IAddressFactory])

    nameKind = URL_KIND
    nameAttr = None
    supportedSchemes = ()

    def supportsScheme(klass, scheme):
        return scheme in klass.supportedSchemes or not klass.supportedSchemes

    supportsScheme = classmethod(supportsScheme)

    def __init__(self, scheme=None, body='', **__kw):

        scheme = scheme or self.__class__.defaultScheme

        if body:
            data = self.parse(scheme, str(body))
            data.update(__kw)
            __kw = data

        __kw['scheme'] = scheme
        __kw['body'] = body

        for f in self.__class__.mdl_features:
            if f.isRequired and not f.attrName in __kw:
                raise exceptions.InvalidName("Missing %s field in %r" %
                                             (f.attrName, __kw))

        super(Base, self).__init__(**__kw)
        self.__class__.body._setup(self, self.getCanonicalBody())

    class scheme(RequiredField):

        _defaultValue = classAttr(Obtain('defaultScheme'))

        def _onLink(feature, element, item, posn):
            # delegate scheme validation to element class
            if not element.supportsScheme(item):
                raise exceptions.InvalidName("Unsupported scheme %r for %r" %
                                             (item, element.__class__))

    class body(NameField):
        defaultValue = ''
        unquote = False
        canBeEmpty = True

    syntax = body._syntax  # default syntax is just to parse the body

    def mdl_fromString(klass, aName):
        m = URLMatch(aName)
        if m:
            return klass(m.group(1), aName[m.end():])
        else:
            return klass(None, aName)

    def __str__(self):
        return "%s:%s" % (self.scheme, self.body)

    # "inherit" findComponent() method from names
    findComponent = CompoundName.findComponent.im_func

    __add__ = name_add
    __sub__ = name_sub
    __radd__ = name_radd
    __rsub__ = name_rsub

    def addName(self, other):

        if not other:
            return self

        name = adapt(other, IName, None)

        if name is None:
            raise TypeError("Only names can be added to URLs", self, other)

        other = name
        if other.nameKind == URL_KIND:
            return other

        na = self.nameAttr

        if not na:
            raise TypeError("Addition not supported for pure address types",
                            self, other)

        d = dict(self._hashAndCompare)
        d['body'] = None  # before the below in case 'na' is "body"
        d[na] = getattr(self, na, CompoundName(())) + other

        res = self.__class__(**d)
        return res

    def __split(self):

        d = dict(self._hashAndCompare)
        na = self.nameAttr

        if na:
            if na in d:
                nic = d[na]
                del d[na]
            else:
                nic = getattr(self, na)
        else:
            nic = CompoundName(())

        d['body'] = ''
        auth = self.__class__(**d)
        return auth, nic

    __split = Make(__split)

    def getAuthorityAndName(self):
        return self.__split

    def __repr__(self):
        return "%s(%s)" % (self.__class__.__name__, ','.join(
            ['%s=%r' % (k, v) for (k, v) in self._hashAndCompare]))

    def _hashAndCompare(self):
        klass = self.__class__
        omitBody = len(klass.mdl_featureNames) != 2  # ('scheme','body')
        return tuple([(f, getattr(self, f))
                      for f in self.__class__.mdl_featureNames
                      if (not omitBody or f != 'body')])

    _hashAndCompare = Make(_hashAndCompare)

    def parse(klass, scheme, body):
        if klass.syntax is not None:
            return parse(body, klass.syntax)

        return {}

    parse = classmethod(parse)

    def getCanonicalBody(self):
        if self.__class__.syntax is not None:
            return format(dict(self._hashAndCompare), self.__class__.syntax)
        return self.body

    defaultScheme = classAttr(
        Make(lambda self: self.supportedSchemes and self.supportedSchemes[0] or
             None))

    def getURLContext(klass,
                      parent,
                      scheme,
                      iface,
                      componentName=None,
                      **options):
        if klass.supportsScheme(scheme):
            from contexts import AddressContext
            return AddressContext(parent,
                                  componentName,
                                  schemeParser=klass,
                                  **options)

    getURLContext = classmethod(getURLContext)

    def __adapt__(klass, ob):
        """Allow address classes to be used as protocols"""
        if isinstance(ob, str):
            return klass.mdl_fromString(ob)

    __adapt__ = classAttr(protocols.metamethod(__adapt__))