Example #1
0
class SQLModTime(SQLGatewayBase):
    """SQL object mod time gateway"""

    __implements__ = SQLGatewayBase.__implements__

    schema = ColumnSchema('mtime', 'int')  # second
    table_name = 'mtime'
    table_schema = RowSequenceSchema()
    table_schema.add('mtime', 'long', 0)

    def load(self, event):
        table = self.get_table(event)
        items = table.select(self.column_names, oid=event.oid)
        if items:
            state = long(items[0][0])
        else:
            state = 0L
        return state, state

    def store(self, event, state):
        state = long(state)
        table = self.get_table(event)
        data = (state, )
        table.set_one(event.oid, self.column_names, data, event.is_new)
        return state
Example #2
0
class SQLClassification(SQLGatewayBase):

    __implements__ = SQLGatewayBase.__implements__

    schema = ColumnSchema('classification', 'classification')
    table_name = 'classification'
    table_schema = RowSequenceSchema()
    table_schema.add('class_name', 'string', 0)
    table_schema.add('mapper_name', 'string', 0)

    def load(self, event):
        table = self.get_table(event)
        rows = table.select(self.column_names, oid=event.oid)
        classification = {}
        if rows:
            rec = rows[0]
            if rec[0]:
                classification['class_name'] = rec[0]
            if rec[1]:
                classification['mapper_name'] = rec[1]
        else:
            raise KeyError(event.oid)
        return classification, rec

    def store(self, event, classification):
        conn = self.get_connection(event)
        table = self.get_table(event)
        row = (classification.get('class_name',
                                  ''), classification.get('mapper_name', ''))
        try:
            table.set_one(event.oid, self.column_names, row, event.is_new)
        except conn.module.DatabaseError:
            raise OIDConflictError(event.oid)
        return row
Example #3
0
class IdAttribute:
    """Zope 2 id attribute."""

    __implements__ = ISerializer

    schema = ColumnSchema('id', 'string')

    def can_serialize(self, obj):
        return 1

    def _get_attr_name_for(self, obj):
        if isinstance(obj, Item_w__name__):
            return '__name__'
        else:
            return 'id'

    def serialize(self, event):
        obj = event.obj
        attrname = self._get_attr_name_for(obj)
        id = getattr(obj, attrname)
        if not id:
            raise SerializationError('ID of %r is %r' % (obj, id))
        event.serialized(attrname, id, 1)
        return id

    def deserialize(self, event, state):
        obj = event.obj
        attrname = self._get_attr_name_for(obj)
        setattr(obj, attrname, state)
        # Allow references under either attribute name.
        event.deserialized('id', state)
        event.deserialized('__name__', state)
Example #4
0
class FilePData:
    """Serializer of the 'data' attribute of OFS.File and OFS.Image"""

    __implements__ = ISerializer

    schema = ColumnSchema('data', 'string')

    def can_serialize(self, object):
        return isinstance(object, File)

    def serialize(self, event):
        obj = event.obj
        event.serialized('data', obj.data, 1)
        event.ignore(('size', 'width', 'height'))
        return str(obj.data)

    def deserialize(self, event, state):
        obj = event.obj
        data, size = obj._read_data(state)
        if not obj.__dict__.get('content_type'):
            # Guess the content type.
            content_type = obj._get_content_type(state, data, obj.__name__)
        else:
            # The properties serializer is authoritative.  Defer to it.
            content_type = None
        obj.update_data(data, content_type, size)
        event.deserialized('data', obj.data)
Example #5
0
class FSFileData(FSGatewayBase):
    """File data gateway, where data is a string.
    """

    __implements__ = IGateway

    schema = ColumnSchema('data', 'string')

    def __init__(self, text=0, conn_name='fs'):
        if text == 'text':
            text = 1
        elif text == 'binary':
            text = 0
        self.text = text
        FSGatewayBase.__init__(self, conn_name)

    def load(self, event):
        c = self.get_connection(event)
        assert c.read_node_type(event.oid) == 'f'
        state = c.read_data(event.oid, as_text=self.text)
        return state, state

    def store(self, event, state):
        if not isinstance(state, StringType):
            raise ValueError('Not a string: %s' % repr(state))
        c = self.get_connection(event)
        c.write_node_type(event.oid, 'f')
        c.write_data(event.oid, state, as_text=self.text)
        return state
Example #6
0
class SQLItemId(SQLGatewayBase):
    """SQL item ID gateway.

    Piggybacks SQLFolderItems for init and store.
    Makes the assumption that the item is stored in only one place.
    """

    __implements__ = SQLGatewayBase.__implements__

    schema = ColumnSchema('id', 'string')
    table_name = 'folder_items'
    table_schema = RowSequenceSchema()
    table_schema.add('child_oid', 'int', 1)
    table_schema.add('name', 'string', 0)

    def init(self, event):
        pass

    def load(self, event):
        table = self.get_table(event)
        rows = table.select(('name', ), child_oid=event.oid)
        if len(rows) >= 1:
            name = rows[0][0]  # Accept only the first result
        else:
            name = None
        # Disable conflict checking by returning None as the hash value.
        return name, None

    def store(self, event, state):
        return None
Example #7
0
class SQLObjectData(SQLGatewayBase):
    """SQL object data gateway"""

    __implements__ = SQLGatewayBase.__implements__

    schema = ColumnSchema('data', 'string')
    table_name = 'object_data'
    table_schema = RowSequenceSchema()
    table_schema.add('data', 'blob', 0)

    def load(self, event):
        table = self.get_table(event)
        firstcol = self.column_names[:1]
        items = table.select(firstcol, oid=event.oid)
        if items:
            state = str(items[0][0])
        else:
            state = ''
        return state, state

    def store(self, event, state):
        conn = self.get_connection(event)
        table = self.get_table(event)
        firstcol = self.column_names[:1]
        data = (state, )
        table.set_one(event.oid, firstcol, data, event.is_new)
        return state
Example #8
0
class ModTimeAttribute:
    """Sets the _p_mtime attribute.

    XXX Due to a ZODB limitation, this class has to set the _p_mtime
    by setting _p_serial.
    """

    __implements__ = ISerializer

    schema = ColumnSchema('mtime', 'int')

    def can_serialize(self, obj):
        return is_persistent(obj)

    def _set_time(self, obj, t):
        """Sets the last modification time of a Persistent obj to float t.
        """
        args = time.gmtime(t)[:5] + (t%60,)
        obj._p_serial = repr(TimeStamp(*args))

    def serialize(self, event):
        now = long(time.time())
        if event.obj._p_changed:
            # Indicate that this object just changed.  Note that the time
            # is a guess.
            self._set_time(event.obj, now)
        return now

    def deserialize(self, event, state):
        self._set_time(event.obj, state)
Example #9
0
class SQLSecurityAttributes(SQLGatewayBase):
    """SQL security attribute storage"""

    __implements__ = SQLGatewayBase.__implements__

    schema = RowSequenceSchema()
    schema.add('declaration_type', 'string')
    schema.add('role', 'string')
    schema.add('permission', 'string')
    schema.add('username', 'string')

    table_name = 'security'
    oid_columns = [ColumnSchema('oid', 'int', 0)]  # Don't create a primary key

    def load(self, event):
        table = self.get_table(event)
        items = table.select(self.column_names, oid=event.oid)
        items.sort()
        return items, tuple(items)

    def store(self, event, state):
        table = self.get_table(event)
        table.set_many(event.oid, (), self.column_names, state)
        state = list(state)
        state.sort()
        return tuple(state)
Example #10
0
class SQLGatewayBase:
    """SQL gateway base class"""

    __implements__ = IGateway, IDatabaseInitializer

    # override these in subclasses
    table_name = None
    schema = None
    table_schema = None
    oid_columns = [ColumnSchema('oid', 'int', 1)]

    def __init__(self, conn_name='db'):
        self.conn_name = conn_name
        if self.table_schema is None:
            if self.schema is not None:
                self.table_schema = self.schema
            else:
                self.table_schema = RowSequenceSchema()
        self.column_names = [f.name for f in self.table_schema.get_columns()]

    def get_connection(self, event):
        return event.connections[self.conn_name]

    def get_table(self, event):
        c = event.connections[self.conn_name]
        return c.get_table(self.table_name)

    def create(self, event):
        self.get_table(event).create()

    def init(self, event):
        conn = self.get_connection(event)
        assert IRDBMSConnection.isImplementedBy(conn)
        all = RowSequenceSchema(
            self.oid_columns + self.table_schema.get_columns())
        table = conn.define_table(self.table_name, all)
        if conn.exists(self.table_name, 'table'):
            if IDatabaseInitEvent.isImplementedBy(event) and event.clear_all:
                table.delete_rows()
        else:
            table.create()

    def load(self, event):
        raise NotImplementedError, "abstract method"

    def store(self, event, obj):
        raise NotImplementedError, "abstract method"

    def get_sources(self, event):
        return None
Example #11
0
class FSModTime(FSGatewayBase):
    """Reads the modification time of a file."""

    __implements__ = IGateway

    schema = ColumnSchema('mtime', 'int')

    def load(self, event):
        fs_conn = self.get_connection(event)
        state = long(fs_conn.read_mod_time(event.oid))
        return state, None  # Use None as the hash (see store())

    def store(self, event, state):
        # Under normal circumstances, there is no need to change the mod
        # time of a file.  Ignore by returning None as the hash.
        return None
Example #12
0
class FSClassificationAnnotation(FSGatewayBase):
    """Gateway for storing classification data."""

    __implements__ = IGateway

    schema = ColumnSchema('classification', 'classification')

    def load(self, event):
        fs_conn = self.get_connection(event)
        oid = event.oid
        classification = {'node_type': fs_conn.read_node_type(oid)}
        text = fs_conn.read_annotation(oid, 'classification', '')
        if text:
            lines = text.split('\n')
            for line in lines:
                if '=' in line:
                    k, v = line.split('=', 1)
                    classification[k.strip()] = v.strip()
        classification['extension'] = fs_conn.read_extension(oid)
        classification['subpath'] = fs_conn.get_subpath(oid)
        return classification, text.strip()

    def store(self, event, state):
        # state is a classification
        fs_conn = self.get_connection(event)
        oid = event.oid
        if event.is_new:
            # Don't overwrite existing data
            try:
                fs_conn.read_node_type(oid)
            except LoadError:
                # Nothing exists yet.
                pass
            else:
                # Something exists.  Don't overwrite it.
                raise OIDConflictError(oid)
        items = state.items()
        items.sort()
        text = []
        for k, v in items:
            if k == 'extension':
                fs_conn.suggest_extension(oid, v)
            else:
                text.append('%s=%s' % (k, v))
        text = '\n'.join(text)
        fs_conn.write_annotation(oid, 'classification', text)
        return text.strip()
Example #13
0
class FSAutoId(FSGatewayBase):
    """Automatic ID gateway based on the object name in the primary parent.
    """

    __implements__ = IGateway

    schema = ColumnSchema('id', 'string')

    def load(self, event):
        id = self.get_connection(event).read_object_name(event.oid)
        # Disable conflict checking by returning None as the hash value.
        return id, None

    def store(self, event, state):
        # Ignore.
        return None

    def get_sources(self, event):
        fs_conn = self.get_connection(event)
        return fs_conn.get_sources(event.oid)
Example #14
0
class ZSQLMethodSerializer:
    """Serializer for ZSQLMethods.

    ZSQLMethodSerializer serializes using the same representation
    as FTP or WebDAV.  All computable attributes like compiled code
    are dropped.
    """

    __implements__ = ISerializer

    schema = ColumnSchema('data', 'string')

    params_re = re.compile(r'\s*<params>(.*)</params>\s*\n', re.I | re.S)

    def can_serialize(self, obj):
        return isinstance(obj, SQL)

    def serialize(self, event):
        data = event.obj.document_src()
        event.ignore(('_arg', 'template', 'arguments_src', 'src'))
        return data

    def deserialize(self, event, state):
        obj = event.obj
        assert isinstance(state, StringType)
        assert isinstance(obj, SQL)
        body = state
        m = self.params_re.match(body)
        if m:
            obj.arguments_src = m.group(1)
            body = body[m.end():]
        else:
            obj.arguments_src = ''
        obj._arg = parse(obj.arguments_src)
        obj.src = body
        obj.template = obj.template_class(body)
        obj.template.cook()
        obj._v_cache = ({}, Bucket())
        if not hasattr(obj, 'connection_id'):
            obj.connection_id = ''
Example #15
0
class PythonScriptSerializer:
    """Serializer for PythonScripts.

    PythonScriptSerializer serializes using the same representation
    as FTP or WebDAV.  All computable attributes like compiled code
    are dropped.
    """

    __implements__ = ISerializer

    schema = ColumnSchema('data', 'string')

    def can_serialize(self, obj):
        return isinstance(obj, PythonScript)

    def serialize(self, event):
        assert isinstance(event.obj, PythonScript)
        data = event.obj.read()
        assert isinstance(data, StringType)
        event.ignore((
            'title', '_params', '_body', '_bind_names',
            'warnings', 'errors', '_code', 'Python_magic', 
            'Script_magic', 'func_defaults', 'func_code', 
            'co_varnames', 'co_argcount',
            ))
        return data

    def deserialize(self, event, state):
        obj = event.obj
        assert isinstance(state, StringType)
        assert isinstance(event.obj, PythonScript)
        # Circumvent proxy role checking while deserializing the script.
        obj._validateProxy = lambda: 0
        try:
            obj.write(state) 
            obj._makeFunction()
        finally:
            # Remove the proxy circumvention
            del obj._validateProxy
Example #16
0
class FSAnnotationData(FSGatewayBase):
    """Text to filesystem property annotation gateway."""

    __implements__ = IGateway

    schema = ColumnSchema('data', 'string')

    def __init__(self, annotation, conn_name='fs'):
        self.annotation = str(annotation)
        FSGatewayBase.__init__(self, conn_name)

    def load(self, event):
        fs_conn = self.get_connection(event)
        state = fs_conn.read_annotation(event.oid, self.annotation, '').strip()
        return state, state

    def store(self, event, state):
        if not isinstance(state, StringType):
            raise ValueError('Not a string: %s' % repr(state))
        state = state.strip()
        if state:
            fs_conn = self.get_connection(event)
            fs_conn.write_annotation(event.oid, self.annotation, state)
        return state
Example #17
0
class PersistentMappingSerializer:
    """(de)serializer of a persistent mapping that uses string keys.

    Serializes both references and second-class persistent objects.
    Because of this flexibility, the schema is a little complex.
    """
    __implements__ = ISerializer

    # This schema includes both a list of items that are references to
    # persistent objects and a pickle containing items that are not
    # references.
    schema1 = RowSequenceSchema()
    schema1.add('key', 'string', 1)
    schema1.add('oid', 'string')
    schema1.add('classification', 'classification')
    schema2 = ColumnSchema('data', 'string')
    schema = {'references': schema1, 'others': schema2}

    def can_serialize(self, obj):
        return isinstance(obj, PersistentMapping)

    def serialize(self, event):
        assert self.can_serialize(event.obj)
        refs = []
        others = {}
        for key, value in event.obj.items():
            if is_persistent(value):
                oid = event.obj_db.identify(value)
                if oid is None:
                    oid = event.obj_db.new_oid()
                event.referenced(key, value, False, oid)
                # No need to pass classification.
                refs.append((key, oid, None))
            else:
                event.serialized(key, value, False)
                others[key] = value
        event.ignore(('data', '_container'))
        if others:
            # Encode as a sorted list to preserve order.
            others_list = others.items()
            others_list.sort()
            s = encode_to_text(dumps(others_list, 1), others.keys())
        else:
            s = ''
        return {'references': refs, 'others': s}

    def deserialize(self, event, state):
        assert self.can_serialize(event.obj)
        data_dict = {}
        s = state['others']
        if s:
            s = decode_from_text(s)
            if s:
                data = loads(s)
                if hasattr(data, 'items'):
                    # Stored as a dictionary
                    data_list = data.items()
                    data_dict = data
                else:
                    # Stored as a sequence of tuples
                    data_list = data
                    for key, value in data:
                        data_dict[key] = value
                for key, value in data_list:
                    event.deserialized(key, value)
        for (key, oid, classification) in state['references']:
            value = event.resolve(key, oid, classification)
            data_dict[key] = value
        event.obj.__init__(data_dict)
Example #18
0
class RemainingState:
    """(De)serializes the remaining state of a Persistent object"""

    __implements__ = ISerializer

    schema = ColumnSchema('data', 'string')

    def can_serialize(self, obj):
        return is_persistent(obj)

    def serialize(self, event):
        assert IFullSerializationEvent.isImplementedBy(event)
        assert isinstance(event.obj, Persistent)

        # Allow pickling of cyclic references to the object.
        event.serialized('self', event.obj, False)

        # Ignore previously serialized attributes
        state = event.obj.__dict__.copy()
        for key in state.keys():
            if key.startswith('_v_'):
                del state[key]
        for attrname in event.get_seralized_attributes():
            if state.has_key(attrname):
                del state[attrname]
        if not state:
            # No data needs to be stored
            return ''

        outfile = StringIO()
        p = Pickler(outfile, 1)  # Binary pickle
        unmanaged = []

        def persistent_id(ob, identify_internal=event.identify_internal,
                          unmanaged=unmanaged):
            ref = identify_internal(ob)
            if ref is None:
                if hasattr(ob, '_p_oid'):
                    # Persistent objects that end up in the remainder
                    # are unmanaged.  Tell ZODB about them so that
                    # ZODB can deal with them specially.
                    unmanaged.append(ob)
            return ref

        # Preserve order to a reasonable extent by storing a list
        # instead of a dictionary.
        state_list = state.items()
        state_list.sort()
        p.persistent_id = persistent_id
        try:
            p.dump(state_list)
        except UnpickleableError, exc:
            # Try to reveal which attribute is unpickleable.
            attrname = None
            attrvalue = None
            for key, value in state_list:
                del unmanaged[:]
                outfile.seek(0)
                outfile.truncate()
                p = Pickler(outfile)
                p.persistent_id = persistent_id
                try:
                    p.dump(value)
                except UnpickleableError:
                    attrname = key
                    attrvalue = value
                    break
            if attrname is not None:
                # Provide a more informative exception.
                if os.environ.get('APE_TRACE_UNPICKLEABLE'):
                    # Provide an opportunity to examine
                    # the "attrvalue" attribute.
                    import pdb
                    pdb.set_trace()
                raise RuntimeError(
                    'Unable to pickle the %s attribute, %s, '
                    'of %s at %s.  %s.' % (
                    repr(attrname), repr(attrvalue), repr(event.obj),
                    repr(event.oid), str(exc)))
            else:
                # Couldn't help.
                raise

        p.persistent_id = lambda ob: None  # Stop recording references
        p.dump(unmanaged)
        event.upos.extend(unmanaged)

        s = outfile.getvalue()
        return encode_to_text(s, state.keys(), len(unmanaged))