def dragSourceRegister(widget, action='copy', datatype='text/uri-list',
                       data=''):
    """
    if the 'data' param is callable, it will be called every time to
    look up the current data.

    If the callable returns None (or data is None to begin with), the drag
    """
    widget.tk.call('tkdnd::drag_source', 'register', widget._w)

    # with normal Tkinter bind(), the result of your handler isn't
    # actually returned so the drag doesn't get launched. This is a
    # corrected version of what bind() does when you pass a function,
    # but I don't block my tuple from getting returned (as a tcl list)

    def init():
        dataValue = data() if callable(data) else data
        if dataValue is None:
            return
        return (action, datatype, dataValue)

    funcId = widget._register(
        init,
        widget._substitute,
        1  # needscleanup
    )
    widget.bind("<<DragInitCmd>>", funcId)