def _introspect(self):
        """
            Introspect the field type and constraints, generate model,
            binding and widget and extract i18n strings. The results
            can be accessed via the lazy properties model, binding, widget,
            and strings.

            @return: nothing
        """

        field = self.field

        # Initialize i18n strings
        self._strings = {}

        # Tag for the model
        self._model = TAG[self.name]()

        # Is the field writable/required?
        readonly = None # "false()"
        required = None # "false()"
        if not field.writable:
            readonly = "true()"
        elif self._required(field):
            required = "true()"

        # Basic binding attributes
        attr = {"_nodeset": self.ref,
                "_required": required,
                "_readonly": readonly,
                }

        # Get the xforms field type
        fieldtype = self.types.get(str(field.type), "string")

        # Introspect validators
        requires = field.requires
        options = False
        multiple = False
        if requires:
            if not isinstance(requires, list):
                requires = [requires]
            # Does the field have options?
            first = requires[0]
            if hasattr(first, "options"):
                options = True
                if hasattr(first, "multiple") and first.multiple:
                    multiple = True
            # Does the field have a minimum and/or maximum constraint?
            elif fieldtype in ("decimal", "int", "date", "datetime"):
                constraint = self._range(requires)
                if constraint:
                    attr["_constraint"] = constraint

        # Add the field type to binding
        if not options:
            attr["_type"] = fieldtype

        # Binding
        self._binding = TAG["bind"](**attr)

        # Determine the widget
        if hasattr(field, "xform"):
            # Custom widget
            widget = field.xform
        else:
            # Determine the widget type
            if not field.writable:
                widget_type = "readonly"
            else:
                widget_type = str(field.type)
                if options:
                    if multiple:
                        widget_type = "multiple"
                    else:
                        widget_type = "options"

            widgets = self.widgets
            if widgets in widget_type:
                widget = widgets[widget_type]
            else:
                widget = None

        if widget is not None:
            # Instantiate the widget if necessary
            if isinstance(widget, type):
                widget = widget(translate=self.translate)

            # Get the label
            if hasattr(field, "label"):
                label = field.label
            else:
                label = None
            if not label:
                label = current.T(" ".join(s.capitalize()
                                  for s in self.name.split("_")).strip())

            # Render the widget and update i18n strings
            self._widget, strings = widget(field, label, self.ref)
            if self.translate:
                self._strings.update(strings)
        else:
            # Unsupported widget type => render an empty tag
            self._widget = TAG[""]()

        return

    # -------------------------------------------------------------------------
dataset/ETHPy150Open sahana/eden/modules/s3/s3xforms.py/S3XFormsField._introspect/swapped operands of `in`