<commit_before>import inspect

from graceful.validators import min_validator, max_validator


class BaseField:
    """Base field class for subclassing.

    To create new field type subclass :any:`BaseField` and implement following
    methods:

    * ``from_representation()``: converts representation (used in
      request/response body) to internal value.

    * ``to_representation()``: converts internal value to representation
      that will be used in response body.


    Args:
        details (str): human readable description of field (it will be used
            for describing resource on OPTIONS requests).

        label (str): human readable label of a field (it will be used for
            describing resource on OPTIONS requests).

            *Note: it is recommended to use field names that are
            self-explanatory intead of relying on field labels.*

        source (str): name of internal object key/attribute that will be
            passed to field on ``.to_representation()`` call. Special ``'*'``
            value is allowed that will pass whole object to field when making
            representation. If not set then default source will
            be a field name used as a serializer's attribute.

        validators (list): list of validator callables.

        many (bool): set to True if field is in fact a list of given type
           objects.

        read_only (bool): True if field is read-only and cannot be set/modified
            via POST, PUT, or PATCH requests.

        write_only (bool): True if field is write-only and cannot be retrieved
            via GET requests.

            .. versionadded:: 0.5.0

    Example:

    .. code-block:: python

        class BoolField(BaseField):
            def from_representation(self, data):
                if data in {'true', 'True', 'yes', '1', 'Y'}:
                    return True:
                elif data in {'false', 'False', 'no', '0', 'N'}:
                    return False:
                else:
                    raise ValueError(
                        "{data} is not valid boolean field".format(
                            data=data
                        )
                    )

            def to_representation(self, value):
                return ["True", "False"][value]

    """

    #: Two-tuple ``(label, url)`` pointing to represented type specification
    #: (for documentation).
    spec = None

    #: String label of represented type (for documentation).
    type = None

    def __init__(
            self,
            details,
            label=None,
            source=None,
            validators=None,
            many=False,
            read_only=False,
            write_only=False,
    ):
        """Initialize field definition."""
        self.label = label
        self.source = source
        self.details = details
        self.validators = validators or []
        self.many = many
        self.read_only = read_only
        self.write_only = write_only

        if self.write_only and self.read_only:
            raise ValueError(
                "Field cannot be read-only and write-only at the same time."
            )

    def from_representation(self, data):
        """Convert representation value to internal value.

        Note:
             This is method handler stub and should be redifined in the
             ``BaseField`` subclasses.

        """
        raise NotImplementedError(
            "{cls}.from_representation() method not implemented".format(
                cls=self.__class__.__name__
            )
        )

    def to_representation(self, value):
        """Convert representation value to internal value.

        Note:
             This is method handler stub and should be redifined in the
             ``BaseField`` subclasses.

        """
        raise NotImplementedError(
            "{cls}.to_representation() method not implemented".format(
                cls=self.__class__.__name__
            )
        )

    def describe(self, **kwargs):
        """
        Describe this field instance for purpose of self-documentation.

        Args:
            kwargs (dict): dictionary of additional description items for
                extending default description

        Returns:
            dict: dictionary of description items

        Suggested way for overriding description fields or extending it with
        additional items is calling super class method with new/overriden
        fields passed as keyword arguments like following:

        .. code-block:: python

            class DummyField(BaseField):
               def description(self, **kwargs):
                   super().describe(is_dummy=True, **kwargs)

        """
        description = {
            'label': self.label,
            'details': inspect.cleandoc(self.details),
            'type': "list of {}".format(self.type) if self.many else self.type,
            'spec': self.spec,
            'read_only': self.read_only,
            'write_only': self.write_only,
        }
        description.update(kwargs)
        return description

    def validate(self, value):
        """Perform validation on value by running all field validators.
<commit_msg>Allow null argument added to the base field. Docs, constructor and description updated with allow_null.<commit_after>import inspect

from graceful.validators import min_validator, max_validator


class BaseField:
    """Base field class for subclassing.

    To create new field type subclass :any:`BaseField` and implement following
    methods:

    * ``from_representation()``: converts representation (used in
      request/response body) to internal value.

    * ``to_representation()``: converts internal value to representation
      that will be used in response body.


    Args:
        details (str): human readable description of field (it will be used
            for describing resource on OPTIONS requests).

        label (str): human readable label of a field (it will be used for
            describing resource on OPTIONS requests).

            *Note: it is recommended to use field names that are
            self-explanatory intead of relying on field labels.*

        source (str): name of internal object key/attribute that will be
            passed to field on ``.to_representation()`` call. Special ``'*'``
            value is allowed that will pass whole object to field when making
            representation. If not set then default source will
            be a field name used as a serializer's attribute.

        validators (list): list of validator callables.

        many (bool): set to True if field is in fact a list of given type
           objects.

        read_only (bool): True if field is read-only and cannot be set/modified
            via POST, PUT, or PATCH requests.

        write_only (bool): True if field is write-only and cannot be retrieved
            via GET requests.

        allow_null (bool): True if field can have intentional `null` values
            which will be interpreted as `None` afterwards.

            .. versionadded:: 0.5.0

    Example:

    .. code-block:: python

        class BoolField(BaseField):
            def from_representation(self, data):
                if data in {'true', 'True', 'yes', '1', 'Y'}:
                    return True:
                elif data in {'false', 'False', 'no', '0', 'N'}:
                    return False:
                else:
                    raise ValueError(
                        "{data} is not valid boolean field".format(
                            data=data
                        )
                    )

            def to_representation(self, value):
                return ["True", "False"][value]

    """

    #: Two-tuple ``(label, url)`` pointing to represented type specification
    #: (for documentation).
    spec = None

    #: String label of represented type (for documentation).
    type = None

    def __init__(
            self,
            details,
            label=None,
            source=None,
            validators=None,
            many=False,
            read_only=False,
            write_only=False,
            allow_null=False,
    ):
        """Initialize field definition."""
        self.label = label
        self.source = source
        self.details = details
        self.validators = validators or []
        self.many = many
        self.read_only = read_only
        self.write_only = write_only
        self.allow_null = allow_null

        if self.write_only and self.read_only:
            raise ValueError(
                "Field cannot be read-only and write-only at the same time."
            )

    def from_representation(self, data):
        """Convert representation value to internal value.

        Note:
             This is method handler stub and should be redifined in the
             ``BaseField`` subclasses.

        """
        raise NotImplementedError(
            "{cls}.from_representation() method not implemented".format(
                cls=self.__class__.__name__
            )
        )

    def to_representation(self, value):
        """Convert representation value to internal value.

        Note:
             This is method handler stub and should be redifined in the
             ``BaseField`` subclasses.

        """
        raise NotImplementedError(
            "{cls}.to_representation() method not implemented".format(
                cls=self.__class__.__name__
            )
        )

    def describe(self, **kwargs):
        """
        Describe this field instance for purpose of self-documentation.

        Args:
            kwargs (dict): dictionary of additional description items for
                extending default description

        Returns:
            dict: dictionary of description items

        Suggested way for overriding description fields or extending it with
        additional items is calling super class method with new/overriden
        fields passed as keyword arguments like following:

        .. code-block:: python

            class DummyField(BaseField):
               def description(self, **kwargs):
                   super().describe(is_dummy=True, **kwargs)

        """
        description = {
            'label': self.label,
            'details': inspect.cleandoc(self.details),
            'type': "list of {}".format(self.type) if self.many else self.type,
            'spec': self.spec,
            'read_only': self.read_only,
            'write_only': self.write_only,
            'allow_null': self.allow_null,
        }
        description.update(kwargs)
        return description

    def validate(self, value):
        """Perform validation on value by running all field validators.

{'fraction_non_alphanumeric': 0.07899860917941585, 'fraction_numerical': 0.0009272137227630969, 'mean_word_length': 1.838421052631579, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '200557', 'n_tokens_mistral': 2644, 'n_tokens_neox': 2497, 'n_words': 980}