def read(self, r, **attr):
        """
            Read a single record

            @param r: the S3Request
            @param attr: dictionary of parameters for the method handler
        """

        # Check authorization to read the record
        authorised = self._permitted()
        if not authorised:
            r.unauthorised()

        request = self.request
        response = current.response

        resource = self.resource
        table = resource.table
        tablename = resource.tablename

        representation = r.representation

        output = dict()

        _config = self._config
        editable = _config("editable", True)

        # Get the target record ID
        record_id = self.record_id

        if r.interactive:

            # If this is a single-component and no record exists,
            # try to create one if the user is permitted
            if not record_id and r.component and not r.component.multiple:
                authorised = self._permitted(method="create")
                if authorised:
                    # This should become Native
                    r.method = "create"
                    return self.create(r, **attr)
                else:
                    return self.select(r, **attr)

            # Redirect to update if user has permission unless
            # a method has been specified in the URL
            # MH: Is this really desirable? Many users would prefer to open as read
            if not r.method: #or r.method == "review":
                authorised = self._permitted("update")
                if authorised and representation == "html" and editable:
                    return self.update(r, **attr)

            # Form configuration
            subheadings = _config("subheadings")

            # Title and subtitle
            crud_string = self.crud_string
            title = crud_string(r.tablename, "title_display")
            output["title"] = title
            if r.component:
                subtitle = crud_string(tablename, "title_display")
                output["subtitle"] = subtitle
            output["title_list"] = crud_string(tablename, "title_list")

            # Item
            if record_id:
                try:
                    item = self.sqlform(request=request,
                                        resource=resource,
                                        record_id=record_id,
                                        readonly=True,
                                        subheadings=subheadings,
                                        format=representation)
                except HTTP, e:
                    message = current.ERROR.BAD_RECORD \
                              if e.status == 404 else e.message
                    r.error(e.status, message)
            else:
                item = DIV(crud_string(tablename, "msg_list_empty"),
                           _class="empty")

            # View
            if representation == "html":
                response.view = self._view(r, "display.html")
                output["item"] = item
            elif representation == "popup":
                response.view = self._view(r, "popup.html")
                output["form"] = item
                caller = attr.get("caller", None)
                output["caller"] = caller
            elif representation == "iframe":
                response.view = self._view(r, "iframe.html")
                output["form"] = item

            # Buttons
            buttons = self.render_buttons(r,
                                          ["edit", "delete", "list", "summary"],
                                          record_id=record_id,
                                          **attr)
            if buttons:
                output["buttons"] = buttons

            # Last update
            last_update = self.last_update()
            if last_update:
                try:
                    output["modified_on"] = last_update["modified_on"]
                except:
                    # Field not in table
                    pass
                try:
                    output["modified_by"] = last_update["modified_by"]
                except:
                    # Field not in table, such as auth_user
                    pass

            # De-duplication
            from s3merge import S3Merge
            output["deduplicate"] = S3Merge.bookmark(r, tablename, record_id)

        elif representation == "plain":
            # e.g. Map Popup
            T = current.T
            fields = [f for f in table if f.readable]
            if r.component:
                if record_id:
                    record = current.db(table._id == record_id).select(limitby=(0, 1),
                                                                       *fields
                                                                       ).first()
                else:
                    record = None
            else:
                record = r.record
            if record:
                # Hide empty fields from popups on map
                for field in fields:
                    try:
                        value = record[field]
                    except:
                        # e.g. gis_location.wkt
                        value = None
                    if value is None or value == "" or value == []:
                        field.readable = False
                item = self.sqlform(request=request,
                                    resource=resource,
                                    record_id=record_id,
                                    readonly=True,
                                    format=representation)

                # Link to Open record
                popup_edit_url = _config("popup_edit_url", None)
                if popup_edit_url and \
                   current.auth.s3_has_permission("update", table, record_id):
                    # Open edit form in iframe
                    details_btn = A(T("Edit"),
                                    _href=popup_edit_url,
                                    _class="btn iframe",
                                    )
                    output["details_btn"] = details_btn
                else:
                    # Open read view in new tab
                    # Set popup_url to "" to have no button present
                    popup_url = _config("popup_url", None)
                    if popup_url is None:
                        popup_url = r.url(method="read", representation="html")
                    if popup_url:
                        details_btn = A(T("Open"),
                                        _href=popup_url,
                                        _class="btn",
                                        _target="_blank",
                                        )
                        output["details_btn"] = details_btn

                # Title and subtitle
                title = self.crud_string(r.tablename, "title_display")
                output["title"] = title

            else:
                item = T("Record not found")

            output["item"] = item
            response.view = self._view(r, "plain.html")

        elif representation == "csv":
            exporter = S3Exporter().csv
            output = exporter(resource)

        #elif representation == "map":
        #    exporter = S3Map()
        #    output = exporter(r, **attr)

        elif representation == "pdf":
            exporter = S3Exporter().pdf
            output = exporter(resource, request=r, **attr)

        elif representation == "shp":
            list_fields = resource.list_fields()
            exporter = S3Exporter().shp
            output = exporter(resource, list_fields=list_fields, **attr)

        elif representation == "svg":
            list_fields = resource.list_fields()
            exporter = S3Exporter().svg
            output = exporter(resource, list_fields=list_fields, **attr)

        elif representation == "xls":
            list_fields = resource.list_fields()
            exporter = S3Exporter().xls
            output = exporter(resource, list_fields=list_fields)

        elif representation == "json":
            exporter = S3Exporter().json

            # Render extra "_tooltip" field for each row?
            get_vars = request.get_vars
            if get_vars in "tooltip":
                tooltip = get_vars["tooltip"]
            else:
                tooltip = None

            output = exporter(resource, tooltip=tooltip)

        else:
            r.error(415, current.ERROR.BAD_FORMAT)

        return output

    # -------------------------------------------------------------------------
dataset/ETHPy150Open sahana/eden/modules/s3/s3crud.py/S3CRUD.read/swapped operands of `in`