Edgewall Software

Extension Point : IAttachmentManipulator


The IAttachmentManipulator can manipulate and validate attachments before saving.


Trac allows users to attach arbitrary files to e.g. tickets or wiki pages. Plugins can hook into the attachment module to tweak the attachment saving process.

The main purpose for this interface is to allow plugins to add new attachment validation rules. Attachments violating these rules are rejected.


Implementing the interface follows the standard guidelines found in TracDev/ComponentArchitecture and of course TracDev/PluginDevelopment.

The validate_attachment method is called when a user adds a new attachment or replaces an existing attachment. Returning a list of messages rejects the attachment, returning [] accepts it.

Note that currently there is no easy way to validate the attachment's file contents. (See #9281) The req parameter contains a file object in req.args['attachment''].file that can be read from. (Make sure to seek back to 0 or only the remaining file content after the current file position may be stored.)

if 'attachment' in req.args:
    upload = req.args['attachment']
        data = upload.file.read(self.sample_size)
        if not is_binary(data):
            content = to_unicode(data)
    filename = upload.filename

The prepare_attachment method should always be implemented as an empty dummy method for compatibility reasons:

    def prepare_attachment(self, req, attachment, fields):


A common use case for attachments is to attach patches to tickets. An open source project might require all such patches to be explicitly licensed under the BSD license. The following minimal example IAttachmentManipulator implementation could enforce such a policy:

from trac.core import Component, implements
from trac.attachment import IAttachmentManipulator
from trac.mimeview.api import get_mimetype

class PatchLicenseChecker(Component):

    def prepare_attachment(self, req, attachment, fields):

    def validate_attachment(self, req, attachment):
        mimetype = get_mimetype(attachment.filename)
        if mimetype == 'text/x-diff' and \
           not attachment.description.contains('BSD'):
           return [('description', "Patches must be released under BSD license")]
        return []

Available Implementations

Additional Information and References

Last modified 10 years ago Last modified on Jul 20, 2012, 10:49:05 PM
Note: See TracWiki for help on using the wiki.