<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def send_file(fd, filename=None, size=None, timestamp=None, ctype=None, charset=CHARSET, attachment=False, wrapper=DEFAULT_WRAPPER):
 """ Send a file represented by file object This function constcuts a HTTPResponse object that uses a file descriptor as response body. The file descriptor is suppled as ``fd`` argument and it must have a ``read()`` method. ``ValueError`` is raised when this is not the case. It supports `byte serving`_ using Range header, and makes the best effort to set all appropriate headers. It also supports HEAD queries. Because we are dealing with file descriptors and not physical files, the user must also supply the file metadata such as filename, size, and timestamp. The ``filename`` argument is an arbitrary filename. It is used to guess the content type, and also to set the content disposition in case of attachments. The ``size`` argument is the payload size in bytes. If it is omitted, the content length header is not set, and byte serving does not work. The ``timestamp`` argument is the number of seconds since Unix epoch when the file was created or last modified. If this argument is omitted, If-Modified-Since request headers cannot be honored. To explicitly specify the content type, the ``ctype`` argument can be used. This should be a valid MIME type of the payload. Default encoding (used as charset parameter in Content-Type header) is 'UTF-8'. This can be overridden by using the ``charset`` argument. The ``attachment`` argumnet can be set to ``True`` to add the Content-Dispositon response header. Value of the header is then set to the filename. The ``wrapper`` argument is used to wrap the file descriptor when doing byte serving. The default is to use ``fdsend.rangewrapper.RangeWrapper`` class, but there are alternatives as ``fdsend.rangewrapper.range_iter`` and ``bottle._file_iter_range``. The wrappers provided by this package are written to specifically handle file handles that do not have a ``seek()`` method. If this is not your case, you may safely use the bottle's wrapper. The primary difference between ``fdsend.rangewrapper.RangeWrapper`` and ``fdsend.rangewrapper.range_iter`` is that the former returns a file-like object with ``read()`` method, which may or may not increase performance when used on a WSGI server that supports ``wsgi.file_wrapper`` feature. The latter returns an iterator and the response is returned as is without the use of a ``file_wrapper``. This may have some benefits when it comes to memory usage. Benchmarking and profiling is the best way to determine which wrapper you want to use, or you need to implement your own. To implement your own wrapper, you need to create a callable or a class that takes the following arguments: - file descriptor - offset (in bytes from start of the file) - length (total number of bytes in the range) The return value of the wrapper must be either an iterable or file-like object that implements ``read()`` and ``close()`` methods with the usual semantics. The code is partly based on ``bottle.static_file``. .. _byte serving: https://tools.ietf.org/html/rfc2616#page-138 """

    if not hasattr(fd, 'read'):
        raise ValueError("Object '{}' has no read() method".format(fd))

    headers = {}
    status = 200

    if not ctype and filename is not None:
        ctype, enc = mimetypes.guess_type(filename)
        if enc:
            headers['Content-Encoding'] = enc

    if ctype:
        if ctype.startswith('text/'):
            # We expect and assume all text files are encoded UTF-8. It's
            # broadcaster's job to ensure this is true.
            ctype += '; charset=%s' % charset
        headers['Content-Type'] = ctype

    if size:
        headers['Content-Length'] = size
        headers['Accept-Ranges'] = 'bytes'

    if timestamp:
        headers['Last-Modified'] = format_ts(timestamp)

        # Check if If-Modified-Since header is in request and respond early
        modsince = request.environ.get('HTTP_IF_MODIFIED_SINCE')
        print(modsince)
        modsince = modsince and parse_date(modsince.split(';')[0].strip())
        if modsince is not None and modsince >= timestamp:
            headers['Date'] = format_ts()
            return HTTPResponse(status=304, **headers)

    if attachment and filename:
        headers['Content-Disposition'] = 'attachment; filename="%s"' % filename

    if request.method == 'HEAD':
        # Request is a HEAD, so remove any fd body
        fd = ''

    ranges = request.environ.get('HTTP_RANGE')
    if size and ranges:
        ranges = list(parse_range_header(ranges, size))
        if not ranges:
            return HTTPError(416, 'Request Range Not Satisfiable')
        start, end = ranges[0]
        headers['Content-Range'] = 'bytes %d-%d/%d' % (start, end - 1, size)
        length = end - start
        headers['Content-Length'] = str(length)
        fd = wrapper(fd, start, length)
        status = 206

    return HTTPResponse(fd, status=status, **headers)