예제 #1
0
파일: core.py 프로젝트: ibis-project/ibis
class DataType(Annotable, Comparable):
    """Base class for all data types.

    [`DataType`][ibis.expr.datatypes.DataType] instances are
    immutable.
    """

    nullable = optional(instance_of(bool), default=True)

    def __call__(self, nullable: bool = True) -> DataType:
        if nullable is not True and nullable is not False:
            raise TypeError(
                "__call__ only accepts the 'nullable' argument. "
                "Please construct a new instance of the type to change the "
                "values of the attributes."
            )
        kwargs = dict(zip(self.argnames, self.args))
        kwargs["nullable"] = nullable
        return self.__class__(**kwargs)

    @property
    def _pretty_piece(self) -> str:
        return ""

    @property
    def name(self) -> str:
        """Return the name of the data type."""
        return self.__class__.__name__

    def __str__(self) -> str:
        prefix = "!" * (not self.nullable)
        return f"{prefix}{self.name.lower()}{self._pretty_piece}"

    def __equals__(
        self,
        other: typing.Any,
    ) -> bool:
        return self.args == other.args

    def equals(self, other):
        if not isinstance(other, DataType):
            raise TypeError(
                "invalid equality comparison between DataType and "
                f"{type(other)}"
            )
        return super().__cached_equals__(other)

    def castable(self, target, **kwargs):
        """Return whether this data type is castable to `target`."""
        return castable(self, target, **kwargs)

    def cast(self, target, **kwargs):
        """Cast this data type to `target`."""
        return cast(self, target, **kwargs)
예제 #2
0
파일: core.py 프로젝트: ibis-project/ibis
class GeoSpatial(DataType):
    """Geospatial values."""

    geotype = optional(isin({"geography", "geometry"}))
    """The specific geospatial type"""

    srid = optional(instance_of(int))
    """The spatial reference identifier."""

    column = ir.GeoSpatialColumn
    scalar = ir.GeoSpatialScalar

    @property
    def _pretty_piece(self) -> str:
        piece = ""
        if self.geotype is not None:
            piece += f":{self.geotype}"
        if self.srid is not None:
            piece += f";{self.srid}"
        return piece
예제 #3
0
파일: core.py 프로젝트: ibis-project/ibis
class Timestamp(DataType):
    """Timestamp values."""

    timezone = optional(instance_of(str))
    """The timezone of values of this type."""

    scalar = ir.TimestampScalar
    column = ir.TimestampColumn

    @property
    def _pretty_piece(self) -> str:
        if (timezone := self.timezone) is not None:
            return f"({timezone!r})"
        return ""
예제 #4
0
파일: core.py 프로젝트: ibis-project/ibis
class Category(DataType):
    cardinality = optional(instance_of(int))

    scalar = ir.CategoryScalar
    column = ir.CategoryColumn

    def __repr__(self):
        if self.cardinality is not None:
            cardinality = repr(self.cardinality)
        else:
            cardinality = "unknown"
        return f"{self.name}(cardinality={cardinality})"

    def to_integer_type(self):
        if self.cardinality is None:
            return int64
        else:
            return infer(self.cardinality)
예제 #5
0
파일: core.py 프로젝트: ibis-project/ibis
class Interval(DataType):
    """Interval values."""

    unit = optional(
        map_to(
            {
                'days': 'D',
                'hours': 'h',
                'minutes': 'm',
                'seconds': 's',
                'milliseconds': 'ms',
                'microseconds': 'us',
                'nanoseconds': 'ns',
                'Y': 'Y',
                'Q': 'Q',
                'M': 'M',
                'W': 'W',
                'D': 'D',
                'h': 'h',
                'm': 'm',
                's': 's',
                'ms': 'ms',
                'us': 'us',
                'ns': 'ns',
            }
        ),
        default="s",
    )
    """The time unit of the interval."""

    value_type = optional(
        compose_of([datatype, instance_of(Integer)]), default=Int32()
    )
    """The underlying type of the stored values."""

    scalar = ir.IntervalScalar
    column = ir.IntervalColumn

    # based on numpy's units
    _units = {
        'Y': 'year',
        'Q': 'quarter',
        'M': 'month',
        'W': 'week',
        'D': 'day',
        'h': 'hour',
        'm': 'minute',
        's': 'second',
        'ms': 'millisecond',
        'us': 'microsecond',
        'ns': 'nanosecond',
    }

    # TODO(kszucs): assert that the nullability if the value_type is equal
    # to the interval's nullability

    @property
    def bounds(self):
        return self.value_type.bounds

    @property
    def resolution(self):
        """The interval unit's name."""
        return self._units[self.unit]

    @property
    def _pretty_piece(self) -> str:
        return f"<{self.value_type}>(unit={self.unit!r})"
예제 #6
0
파일: core.py 프로젝트: ibis-project/ibis
class Decimal(DataType):
    """Fixed-precision decimal values."""

    precision = optional(instance_of(int))
    """The number of decimal places values of this type can hold."""

    scale = optional(instance_of(int))
    """The number of values after the decimal point."""

    scalar = ir.DecimalScalar
    column = ir.DecimalColumn

    def __init__(
        self,
        precision: int | None = None,
        scale: int | None = None,
        **kwargs: Any,
    ) -> None:
        if precision is not None:
            if not isinstance(precision, numbers.Integral):
                raise TypeError(
                    "Decimal type precision must be an integer; "
                    f"got {type(precision)}"
                )
            if precision < 0:
                raise ValueError('Decimal type precision cannot be negative')
            if not precision:
                raise ValueError('Decimal type precision cannot be zero')
        if scale is not None:
            if not isinstance(scale, numbers.Integral):
                raise TypeError('Decimal type scale must be an integer')
            if scale < 0:
                raise ValueError('Decimal type scale cannot be negative')
            if precision is not None and precision < scale:
                raise ValueError(
                    'Decimal type precision must be greater than or equal to '
                    'scale. Got precision={:d} and scale={:d}'.format(
                        precision, scale
                    )
                )
        super().__init__(precision=precision, scale=scale, **kwargs)

    @property
    def largest(self):
        """Return the largest type of decimal."""
        return self.__class__(
            precision=max(self.precision, 38)
            if self.precision is not None
            else None,
            scale=max(self.scale, 2) if self.scale is not None else None,
        )

    @property
    def _pretty_piece(self) -> str:
        args = []

        if (precision := self.precision) is not None:
            args.append(f"prec={precision:d}")

        if (scale := self.scale) is not None:
            args.append(f"scale={scale:d}")