# -*- coding: utf-8 -*-
# pylint: disable=unsubscriptable-object,ungrouped-imports
"""Data Fields
=================
We extends the field classes from :mod:`peewee` with two properties
(:attr:`~flask_datatables.fields.Field.dt_orderable` and
:attr:`~flask_datatables.fields.Field.dt_searchable`) and two
conversion methods (:meth:`~flask_datatables.fields.Field.dt_order`
and :meth:`~flask_datatables.fields.Field.dt_search`) for the integration
with `DataTables`_ server-side processing.
.. _DataTables: https://datatables.net/
"""
from typing import TYPE_CHECKING
import peewee
if TYPE_CHECKING:
from datetime import date, datetime, time
from decimal import Decimal
from typing import Any, Iterable, List, Optional, Tuple, Union
from uuid import UUID
from peewee import SQL
__all__ = [
'Field',
'AutoField',
'BareField',
'BigAutoField',
'BigBitField',
'BigIntegerField',
'BinaryUUIDField',
'BitField',
'BlobField',
'BooleanField',
'CharField',
'DateField',
'DateTimeField',
'DecimalField',
'DoubleField',
'FixedCharField',
'FloatField',
'ForeignKeyField',
'IdentityField',
'IntegerField',
'IPField',
'ManyToManyField',
'PrimaryKeyField',
'SmallIntegerField',
'TextField',
'TimeField',
'TimestampField',
'UUIDField',
]
[docs]
class Field(peewee.Field):
"""Extending :class:`peewee.Field`.
Args:
orderable: Optional[Union[bool, peewee.Field]]: `DataTables`_ orderable field.
searchable: Optional[Union[bool, peewee.Field]]: `DataTables`_ searchable field.
**kwargs: Arbitrary arguments accepted by :class:`peewee.Field`.
If ``orderable`` and/or ``searchable`` is a :obj:`bool` value, it indicates if the
field supports `DataTables`_ ordering and/or searching:
* :data:`True` means the field is orderable and/or searchable, and it will refer to
its properties :attr:`~flask_datatables.fields.Field.dt_orderable` and/or
:attr:`~flask_datatables.fields.Field.dt_searchable` as its default field instance;
.. note::
If the property returns :data:`None`, then the field is orderable and/or searchable
by itself with its own values.
* :data:`False` disables ordering and searching on the field;
* an instance of :class:`peewee.Field` indicates that the current field is orderable
and/or searchable through the given field instance.
Important:
If ``orderable`` and/or ``searchable`` is an instance of :class:`peewee.Field`, then
its attributes :attr:`~flask_datatables.fields.Field.orderable` and/or
:attr:`~flask_datatables.fields.Field.searchable` will be the corresponding instance.
If ``orderable`` and/or ``searchable`` is :data:`True`, then it refers to its properties
:attr:`~flask_datatables.fields.Field.dt_orderable` and/or
:attr:`~flask_datatables.fields.Field.dt_searchable` as the actual value:
* if the properties return an instance of :class:`peewee.Field`, then the attributes will
be the returned instance; i.e. the field is orderable and/or searchable by converting to
the target field instead of itself;
* if the properties return :data:`None`, then the attributes will be :data:`True`; i.e.
the field is orderable and/or searchable by itself with its value.
If ``orderable`` and/or ``searchable`` is :data:`False`, then the attributes will be
:data:`False` as well.
"""
@property
def dt_orderable(self) -> 'Optional[Field]':
"""`DataTables`_ default orderable field."""
@property
def dt_searchable(self) -> 'Optional[Field]':
"""`DataTables`_ default searchable field."""
def __init__(self, orderable: 'Optional[Union[bool, Field]]' = None, searchable: 'Optional[Union[bool, Field]]' = None, # pylint: disable=line-too-long
null: bool = False, index: bool = False, unique: bool = False, column_name: 'Optional[str]' = None,
default: 'Any' = None, primary_key: bool = False, constraints: 'Optional[List[SQL]]' = None,
sequence: 'Optional[str]' = None, collation: 'Optional[str]' = None, unindexed: bool = False, choices: 'Optional[Iterable[Tuple[str, Any]]]' = None, # pylint: disable=line-too-long
help_text: 'Optional[str]' = None, verbose_name: 'Optional[str]' = None, index_type: 'Optional[str]' = None, # pylint: disable=line-too-long
db_column: 'Optional[str]' = None, _hidden: bool = False) -> None:
super().__init__(null=null, index=index, unique=unique, column_name=column_name,
default=default, primary_key=primary_key, constraints=constraints,
sequence=sequence, collation=collation, unindexed=unindexed, choices=choices,
help_text=help_text, verbose_name=verbose_name, index_type=index_type,
db_column=db_column, _hidden=_hidden)
if orderable is None:
orderable = self.dt_orderable or True
if searchable is None:
searchable = self.dt_searchable or True
#: `DataTables`_ integration orderable flag.
self.orderable = orderable # type: Union[bool, Field]
#: `DataTables`_ integration searchable flag.
self.searchable = searchable # type: Union[bool, Field]
[docs]
@staticmethod
def dt_order(value: 'Any') -> 'Any':
"""Convert value for `DataTables`_ ordering operation.
Args:
value: Source value.
Returns:
Converted value.
"""
return value
[docs]
@staticmethod
def dt_search(value: 'Any') -> 'Any':
"""Convert value for `DataTables`_ searching operation.
Args:
value: Source value.
Returns:
Converted value.
"""
return value
[docs]
class IntegerField(peewee.IntegerField, Field):
"""Extending :class:`peewee.IntegerField`."""
@property
def dt_searchable(self) -> 'Optional[Field]':
"""`DataTables`_ default searchable field."""
return TextField(null=True)
[docs]
@staticmethod
def dt_search(value: int) -> str:
"""Convert value for `DataTables`_ searching operation.
Args:
value: Source value.
Returns:
Converted value.
"""
return str(value)
[docs]
class BigIntegerField(peewee.BigIntegerField, IntegerField):
"""Extending :class:`peewee.BigIntegerField`."""
[docs]
class SmallIntegerField(peewee.SmallIntegerField, IntegerField):
"""Extending :class:`peewee.SmallIntegerField`."""
[docs]
class AutoField(peewee.AutoField, IntegerField):
"""Extending :class:`peewee.AutoField`."""
[docs]
class BigAutoField(peewee.BigAutoField, AutoField):
"""Extending :class:`peewee.BigAutoField`."""
[docs]
class IdentityField(peewee.IdentityField, AutoField):
"""Extending :class:`peewee.IdentityField`."""
[docs]
class PrimaryKeyField(peewee.PrimaryKeyField, AutoField):
"""Extending :class:`peewee.PrimaryKeyField`."""
[docs]
class FloatField(peewee.FloatField, Field):
"""Extending :class:`peewee.FloatField`."""
@property
def dt_searchable(self) -> 'Optional[Field]':
"""`DataTables`_ default searchable field."""
return peewee.TextField(null=True)
[docs]
@staticmethod
def dt_search(value: float) -> str:
"""Convert value for `DataTables`_ searching operation.
Args:
value: Source value.
Returns:
Converted value.
"""
return str(value)
[docs]
class DoubleField(peewee.DoubleField, FloatField):
"""Extending :class:`peewee.DoubleField`."""
[docs]
class DecimalField(peewee.DecimalField, Field):
"""Extending :class:`peewee.DecimalField`."""
@property
def dt_searchable(self) -> 'Optional[Field]':
"""`DataTables`_ default searchable field."""
return peewee.TextField(null=True)
[docs]
@staticmethod
def dt_search(value: 'Decimal') -> str:
"""Convert value for `DataTables`_ searching operation.
Args:
value: Source value.
Returns:
Converted value.
"""
return str(value)
class _StringField(peewee._StringField, Field): # pylint: disable=protected-access
"""Extending :class:`peewee._StringField`."""
[docs]
class CharField(peewee.CharField, _StringField):
"""Extending :class:`peewee.CharField`."""
[docs]
class FixedCharField(peewee.FixedCharField, CharField):
"""Extending :class:`peewee.FixedCharField`."""
[docs]
class TextField(peewee.TextField, _StringField):
"""Extending :class:`peewee.TextField`."""
[docs]
class BlobField(peewee.BlobField, Field):
"""Extending :class:`peewee.BlobField`."""
[docs]
class BitField(peewee.BitField, BigIntegerField):
"""Extending :class:`peewee.BitField`."""
[docs]
class BigBitField(peewee.BigBitField, BlobField):
"""Extending :class:`peewee.BigBitField`."""
[docs]
class UUIDField(peewee.UUIDField, Field):
"""Extending :class:`peewee.UUIDField`."""
@property
def dt_searchable(self) -> 'Optional[Field]':
"""`DataTables`_ default searchable field."""
return peewee.CharField(max_length=40, null=True)
[docs]
@staticmethod
def dt_search(value: 'UUID') -> str:
"""Convert value for `DataTables`_ searching operation.
Args:
value: Source value.
Returns:
Converted value.
"""
return str(value)
[docs]
class BinaryUUIDField(peewee.BinaryUUIDField, Field):
"""Extending :class:`peewee.BinaryUUIDField`."""
@property
def dt_searchable(self) -> 'Optional[Field]':
"""`DataTables`_ default searchable field."""
return peewee.CharField(max_length=16, null=True)
[docs]
@staticmethod
def dt_search(value: 'UUID') -> str:
"""Convert value for `DataTables`_ searching operation.
Args:
value: Source value.
Returns:
Converted value.
"""
return str(value)
class _BaseFormattedField(peewee._BaseFormattedField, Field): # pylint: disable=protected-access
"""Extending :class:`peewee._BaseFormattedField`."""
@property
def dt_searchable(self) -> 'Optional[Field]':
"""`DataTables`_ default searchable field."""
return peewee.TextField(null=True)
@staticmethod
def dt_search(value: 'Union[datetime, date, time]') -> str:
"""Convert value for `DataTables`_ searching operation.
Args:
value: Source value.
Returns:
Converted value.
"""
return value.isoformat()
[docs]
class DateTimeField(peewee.DateTimeField, _BaseFormattedField):
"""Extending :class:`peewee.DateTimeField`."""
[docs]
class DateField(peewee.DateField, _BaseFormattedField):
"""Extending :class:`peewee.DateField`."""
[docs]
class TimeField(peewee.TimeField, _BaseFormattedField):
"""Extending :class:`peewee.TimeField`."""
[docs]
class TimestampField(peewee.TimestampField, BigIntegerField):
"""Extending :class:`peewee.TimestampField`."""
[docs]
@staticmethod
def dt_search(value: 'datetime') -> str: # type: ignore[override]
"""Convert value for `DataTables`_ searching operation.
Args:
value: Source value.
Returns:
Converted value.
"""
return value.isoformat()
[docs]
class IPField(peewee.IPField, BigIntegerField):
"""Extending :class:`peewee.IPField`."""
[docs]
@staticmethod
def dt_search(value: str) -> str: # type: ignore[override]
"""Convert value for `DataTables`_ searching operation.
Args:
value: Source value.
Returns:
Converted value.
"""
return value
[docs]
class BooleanField(peewee.BooleanField, Field):
"""Extending :class:`peewee.BooleanField`."""
@property
def dt_searchable(self) -> 'Optional[Field]':
"""`DataTables`_ default searchable field."""
return peewee.CharField(max_length=5, null=True)
[docs]
@staticmethod
def dt_search(value: bool) -> str:
"""Convert value for `DataTables`_ searching operation.
Args:
value: Source value.
Returns:
Converted value.
"""
return 'true' if value else 'false'
[docs]
class BareField(peewee.BareField, Field):
"""Extending :class:`peewee.BareField`."""
[docs]
class ForeignKeyField(peewee.ForeignKeyField, Field):
"""Extending :class:`peewee.ForeignKeyField`."""
class DeferredForeignKey(peewee.DeferredForeignKey, Field):
"""Extending :class:`peewee.DeferredForeignKey`."""
[docs]
class ManyToManyField(peewee.ManyToManyField, Field):
"""Extending :class:`peewee.ManyToManyField`."""
class VirtualField(peewee.VirtualField, Field):
"""Extending :class:`peewee.VirtualField`."""