declarative.py :  » Database » SQLObject » SQLObject-0.12.4 » sqlobject » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Database » SQLObject 
SQLObject » SQLObject 0.12.4 » sqlobject » declarative.py
"""
Declarative objects.

Declarative objects have a simple protocol: you can use classes in
lieu of instances and they are equivalent, and any keyword arguments
you give to the constructor will override those instance variables.
(So if a class is received, we'll simply instantiate an instance with
no arguments).

You can provide a variable __unpackargs__ (a list of strings), and if
the constructor is called with non-keyword arguments they will be
interpreted as the given keyword arguments.

If __unpackargs__ is ('*', name), then all the arguments will be put
in a variable by that name.

You can define a __classinit__(cls, new_attrs) method, which will be
called when the class is created (including subclasses).  Note: you
can't use super() in __classinit__ because the class isn't bound to a
name.  As an analog to __classinit__, Declarative adds
__instanceinit__ which is called with the same argument (new_attrs).
This is like __init__, but after __unpackargs__ and other factors have
been taken into account.

If __mutableattributes__ is defined as a sequence of strings, these
attributes will not be shared between superclasses and their
subclasses.  E.g., if you have a class variable that contains a list
and you append to that list, changes to subclasses will effect
superclasses unless you add the attribute here.

Also defines classinstancemethod, which acts as either a class method
or an instance method depending on where it is called.
"""

import copy
import events

import itertools
counter = itertools.count()

__all__ = ('classinstancemethod', 'DeclarativeMeta', 'Declarative')


class classinstancemethod(object):
    """
    Acts like a class method when called from a class, like an
    instance method when called by an instance.  The method should
    take two arguments, 'self' and 'cls'; one of these will be None
    depending on how the method was called.
    """

    def __init__(self, func):
        self.func = func

    def __get__(self, obj, type=None):
        return _methodwrapper(self.func, obj=obj, type=type)

class _methodwrapper(object):

    def __init__(self, func, obj, type):
        self.func = func
        self.obj = obj
        self.type = type

    def __call__(self, *args, **kw):
        assert not kw.has_key('self') and not kw.has_key('cls'), (
            "You cannot use 'self' or 'cls' arguments to a "
            "classinstancemethod")
        return self.func(*((self.obj, self.type) + args), **kw)

    def __repr__(self):
        if self.obj is None:
            return ('<bound class method %s.%s>'
                    % (self.type.__name__, self.func.func_name))
        else:
            return ('<bound method %s.%s of %r>'
                    % (self.type.__name__, self.func.func_name, self.obj))

class DeclarativeMeta(type):

    def __new__(meta, class_name, bases, new_attrs):
        post_funcs = []
        early_funcs = []
        events.send(events.ClassCreateSignal,
                    bases[0], class_name, bases, new_attrs,
                    post_funcs, early_funcs)
        cls = type.__new__(meta, class_name, bases, new_attrs)
        for func in early_funcs:
            func(cls)
        if new_attrs.has_key('__classinit__'):
            cls.__classinit__ = staticmethod(cls.__classinit__.im_func)
        cls.__classinit__(cls, new_attrs)
        for func in post_funcs:
            func(cls)
        return cls

class Declarative(object):

    __unpackargs__ = ()

    __mutableattributes__ = ()

    __metaclass__ = DeclarativeMeta

    __restrict_attributes__ = None

    def __classinit__(cls, new_attrs):
        cls.declarative_count = counter.next()
        for name in cls.__mutableattributes__:
            if not new_attrs.has_key(name):
                setattr(cls, copy.copy(getattr(cls, name)))

    def __instanceinit__(self, new_attrs):
        if self.__restrict_attributes__ is not None:
            for name in new_attrs:
                if name not in self.__restrict_attributes__:
                    raise TypeError(
                        '%s() got an unexpected keyword argument %r'
                        % (self.__class__.__name__, name))
        for name, value in new_attrs.items():
            setattr(self, name, value)
        if not new_attrs.has_key('declarative_count'):
            self.declarative_count = counter.next()

    def __init__(self, *args, **kw):
        if self.__unpackargs__ and self.__unpackargs__[0] == '*':
            assert len(self.__unpackargs__) == 2, \
                   "When using __unpackargs__ = ('*', varname), you must only provide a single variable name (you gave %r)" % self.__unpackargs__
            name = self.__unpackargs__[1]
            if kw.has_key(name):
                raise TypeError(
                    "keyword parameter '%s' was given by position and name"
                    % name)
            kw[name] = args
        else:
            if len(args) > len(self.__unpackargs__):
                raise TypeError(
                    '%s() takes at most %i arguments (%i given)'
                    % (self.__class__.__name__,
                       len(self.__unpackargs__),
                       len(args)))
            for name, arg in zip(self.__unpackargs__, args):
                if kw.has_key(name):
                    raise TypeError(
                        "keyword parameter '%s' was given by position and name"
                        % name)
                kw[name] = arg
        if kw.has_key('__alsocopy'):
            for name, value in kw['__alsocopy'].items():
                if not kw.has_key(name):
                    if name in self.__mutableattributes__:
                        value = copy.copy(value)
                    kw[name] = value
            del kw['__alsocopy']
        self.__instanceinit__(kw)

    def __call__(self, *args, **kw):
        kw['__alsocopy'] = self.__dict__
        return self.__class__(*args, **kw)

    def singleton(self, cls):
        if self:
            return self
        name = '_%s__singleton' % cls.__name__
        if not hasattr(cls, name):
            setattr(cls, name, cls(declarative_count=cls.declarative_count))
        return getattr(cls, name)
    singleton = classinstancemethod(singleton)

    def __repr__(self, cls):
        if self:
            name = '%s object' % self.__class__.__name__
            v = self.__dict__.copy()
        else:
            name = '%s class' % cls.__name__
            v = cls.__dict__.copy()
        if v.has_key('declarative_count'):
            name = '%s %i' % (name, v['declarative_count'])
            del v['declarative_count']
        # @@: simplifying repr:
        #v = {}
        names = v.keys()
        args = []
        for n in self._repr_vars(names):
            args.append('%s=%r' % (n, v[n]))
        if not args:
            return '<%s>' % name
        else:
            return '<%s %s>' % (name, ' '.join(args))

    def _repr_vars(dictNames):
        names = [n for n in dictNames
                 if not n.startswith('_')
                 and n != 'declarative_count']
        names.sort()
        return names
    _repr_vars = staticmethod(_repr_vars)

    __repr__ = classinstancemethod(__repr__)

def setup_attributes(cls, new_attrs):
    for name, value in new_attrs.items():
        if hasattr(value, '__addtoclass__'):
            value.__addtoclass__(cls, name)

www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.