Exemplo n.º 1
0
    def __init__(cls, cl_name, bases, namespace):
        # add a dictionary to store projections for this class.
        cls._projections = {}
        # tablename guessing
        if namespace.get("table") is not None:
            # table has been explicitly declared, so
            # turn off guess_tablename for subclasses
            if not namespace.has_key("guess_tablename"):
                cls.guess_tablename = False
        elif cls.guess_tablename:
            # leave guess_tablename for subclasses
            cls.table = cl_name.lower()

        # sequence mapping
        sequence_mapper = namespace.get("sequence_mapper")
        if isfunction(sequence_mapper):
            cls.sequence_mapper = staticmethod(sequence_mapper)
        else:
            cls.sequence_mapper = sequence_mapper

        # field guessing
        if namespace.get("guess_columns", False):
            if cls.guesscache == True:
                # supply default cache
                cls.guesscache = GuessCache()
            elif isinstance(cls.guesscache, basestring):
                # assume it is a path
                cls.guesscache = GuessCache(cls.guesscache)
            if "fields" in namespace or "unique" in namespace:
                raise ValueError, (
                    "incompatible declarations: guess_columns " "with explicit declaration of fields and/or unique"
                )
            gfields, gunique = cls._getTableDescription()
            namespace["fields"] = gfields.values()
            namespace["unique"] = gunique

        # create Field objects declared locally in this class
        # and store them in a temporary dict
        fielddict = {}
        # we keep track of which fields are declared just with a string;
        # inheritance semantics are a little different for these
        simplefields = set()
        for f in namespace.get("fields", ()):
            # support for tuple syntax for plain Jane fields.
            if isinstance(f, basestring):
                m = _as_pat.match(f)
                if m:
                    name = m.group(1)
                    asname = m.group(2)
                    simplefields.add(asname)
                    f = cls._create_field(name=name, asname=asname)
                else:
                    simplefields.add(f)
                    f = cls._create_field(f)
            elif isinstance(f, dict):
                f = cls._create_field(**f)
            elif isinstance(f, (tuple, list)):
                f = cls._create_field(*f)
            elif not isinstance(f, Field):
                raise ValueError, "cannot coerce into a field: %s" % f

            # add to field container
            fielddict[f.asname] = f

        # handle inheritance of fields and unique declarations.
        # skipping object and dict is a trivial optimization,
        # because we know those classes won't be relevant

        revbases = [x for x in bases[::-1] if x not in (object, dict)]

        cls._fields = {}
        uniqueset = set()
        for b in revbases:
            flds = getattr(b, "_fields", None)
            if flds:
                if cls._is_projection:
                    flds = _restrict(fielddict, flds)
                cls._fields.update(flds)
            uniq = getattr(b, "unique", None)
            if uniq:
                # transform into a set of sets.  This way,
                # multi-column unique constraints are
                # unordered.
                uniq = set(_setize(x) for x in uniq)
                if cls._is_projection:
                    uniq = _restrict(fielddict, uniq)
                uniqueset.update(uniq)

        # If a field is declared upstream and you redeclare it in a
        # subclass as a simple field (just a fieldname), then the
        # previous field definition is inherited; otherwise, the
        # subclass's definition wins.  This is useful for projections.
        updatefields = ((x, y) for x, y in fielddict.iteritems() if not (x in cls._fields and x in simplefields))
        cls._fields.update(updatefields)
        uniqueset.update(_setize(x) for x in namespace.get("unique", ()))

        # We now have all the inherited declarations, and figure out
        # sequences and additional unique constraints.
        cls._sequenced = {}
        for f in cls._fields.itervalues():
            if f.sequence:
                cls._sequenced[f.asname] = f.sequence
            if f.unique:
                uniqueset.add(frozenset((f.asname,)))

        cls._unique = frozenset(uniqueset)

        # add attribute access to fields
        if cls.use_attributes:
            for name in cls._fields:
                if not hasattr(cls, name):
                    # a field is also a descriptor
                    setattr(cls, name, cls._fields[name])
Exemplo n.º 2
0
    def __init__(cls, cl_name, bases, namespace):
        # add a dictionary to store projections for this class.
        cls._projections = {}
        # tablename guessing
        if namespace.get('table') is not None:
            # table has been explicitly declared, so
            # turn off guess_tablename for subclasses
            if not namespace.has_key('guess_tablename'):
                cls.guess_tablename = False
        elif cls.guess_tablename:
            # leave guess_tablename for subclasses
            cls.table = cl_name.lower()

        # sequence mapping
        sequence_mapper = namespace.get("sequence_mapper")
        if isfunction(sequence_mapper):
            cls.sequence_mapper = staticmethod(sequence_mapper)
        else:
            cls.sequence_mapper = sequence_mapper

        # field guessing
        if namespace.get('guess_columns', False):
            if cls.guesscache == True:
                # supply default cache
                cls.guesscache = GuessCache()
            elif isinstance(cls.guesscache, basestring):
                # assume it is a path
                cls.guesscache = GuessCache(cls.guesscache)
            if 'fields' in namespace or 'unique' in namespace:
                raise ValueError, (
                    "incompatible declarations: guess_columns "
                    "with explicit declaration of fields and/or unique")
            gfields, gunique = cls._getTableDescription()
            namespace['fields'] = gfields.values()
            namespace['unique'] = gunique

        # create Field objects declared locally in this class
        # and store them in a temporary dict
        fielddict = {}
        # we keep track of which fields are declared just with a string;
        # inheritance semantics are a little different for these
        simplefields = set()
        for f in namespace.get('fields', ()):
            # support for tuple syntax for plain Jane fields.
            if isinstance(f, basestring):
                simplefields.add(f)
                f = cls._create_field(f)
            elif isinstance(f, dict):
                f = cls._create_field(**f)
            elif isinstance(f, (tuple, list)):
                f = cls._create_field(*f)
            elif not isinstance(f, Field):
                raise ValueError, "cannot coerce into a field: %s" % f

            # add to field container
            fielddict[f.name] = f

        # handle inheritance of fields and unique declarations.
        # skipping object and dict is a trivial optimization,
        # because we know those classes won't be relevant

        revbases = [x for x in bases[::-1] if x not in (object, dict)]

        cls._fields = {}
        uniqueset = set()
        for b in revbases:
            flds = getattr(b, '_fields', None)
            if flds:
                if cls._is_projection:
                    flds = _restrict(fielddict, flds)
                cls._fields.update(flds)
            uniq = getattr(b, 'unique', None)
            if uniq:
                # transform into a set of sets.  This way,
                # multi-column unique constraints are
                # unordered.
                uniq = set(_setize(x) for x in uniq)
                if cls._is_projection:
                    uniq = _restrict(fielddict, uniq)
                uniqueset.update(uniq)

        # If a field is declared upstream and you redeclare it in a
        # subclass as a simple field (just a fieldname), then the
        # previous field definition is inherited; otherwise, the
        # subclass's definition wins.  This is useful for projections.
        updatefields=((x, y) for x, y in fielddict.iteritems() \
                      if not (x in cls._fields and x in simplefields))
        cls._fields.update(updatefields)
        uniqueset.update(_setize(x) for x in namespace.get('unique', ()))

        # We now have all the inherited declarations, and figure out
        # sequences and additional unique constraints.
        cls._sequenced = {}
        for f in cls._fields.itervalues():
            if f.sequence:
                cls._sequenced[f.name] = f.sequence
            if f.unique:
                uniqueset.add(frozenset((f.name, )))

        cls._unique = frozenset(uniqueset)

        # add attribute access to fields
        if cls.use_attributes:
            for name in cls._fields:
                if not hasattr(cls, name):
                    # a field is also a descriptor
                    setattr(cls, name, cls._fields[name])