예제 #1
0
파일: number.py 프로젝트: wpdavis/agate
    def cast(self, d):
        """
        Cast a single value to a :class:`decimal.Decimal`.

        :returns: :class:`decimal.Decimal` or :code:`None`.
        :raises: :exc:`.CastError`
        """
        if isinstance(d, Decimal) or d is None:
            return d
        elif isinstance(d, int):
            return Decimal(d)
        elif isinstance(d, float):
            raise CastError(
                'Can not convert float to Decimal. Convert data to string first!'
            )
        elif isinstance(d, six.string_types):
            d = d.strip()
            d = d.strip('%')

            for symbol in CURRENCY_SYMBOLS:
                d = d.strip(symbol)

            if d.lower() in self.null_values:
                return None

        try:
            return parse_decimal(d, self._locale)
        except:
            raise CastError('Can not parse value "%s" as Decimal.' % d)
예제 #2
0
    def cast(self, d):
        """
        Cast a single value to :class:`datetime.timedelta`.

        :param d:
            A value to cast.
        :returns:
            :class:`datetime.timedelta` or :code:`None`
        """
        if isinstance(d, datetime.timedelta) or d is None:
            return d
        elif isinstance(d, six.string_types):
            d = d.strip()

            if d.lower() in self.null_values:
                return None
        else:
            raise CastError('Can not parse value "%s" as timedelta.' % d)

        seconds = pytimeparse.parse(d)

        if seconds is None:
            raise CastError('Can not parse value "%s" to as timedelta.' % d)

        return datetime.timedelta(seconds=seconds)
예제 #3
0
    def cast(self, d):
        """
        Cast a single value to a :class:`decimal.Decimal`.

        :returns: :class:`decimal.Decimal` or :code:`None`.
        :raises: :exc:`.CastError`
        """
        if isinstance(d, Decimal) or d is None:
            return d

        if isinstance(d, six.string_types):
            d = d.replace(',', '').strip()

            if d.lower() in self.null_values:
                return None

        if isinstance(d, float):
            raise CastError(
                'Can not convert float to Decimal for NumberColumn. Convert data to string first!'
            )

        try:
            return Decimal(d)
        except InvalidOperation:
            raise CastError(
                'Can not convert value "%s" to Decimal for NumberColumn.' % d)
예제 #4
0
파일: number.py 프로젝트: rdmurphy/agate
    def cast(self, d):
        """
        Cast a single value to a :class:`decimal.Decimal`.

        :returns:
            :class:`decimal.Decimal` or :code:`None`.
        """
        if isinstance(d, Decimal) or d is None:
            return d
        elif type(d) is int:
            return Decimal(d)
        elif type(d) is float:
            return Decimal(repr(d))
        elif isinstance(d, six.string_types):
            d = d.strip()
            d = d.strip('%')

            for symbol in CURRENCY_SYMBOLS:
                d = d.strip(symbol)

            if d.lower() in self.null_values:
                return None
        else:
            raise CastError('Can not parse value "%s" as Decimal.' % d)

        try:
            return parse_decimal(d, self.locale)
        except:
            pass

        raise CastError('Can not parse value "%s" as Decimal.' % d)
예제 #5
0
    def cast(self, d):
        """
        Cast a single value to a :class:`datetime.date`.

        :param date_format:
            An optional :func:`datetime.strptime` format string for parsing
            datetimes in this column.
        :returns:
            :class:`datetime.date` or :code:`None`.
        """
        if type(d) is date or d is None:
            return d
        elif isinstance(d, six.string_types):
            d = d.strip()

            if d.lower() in self.null_values:
                return None
        else:
            raise CastError('Can not parse value "%s" as date.' % d)

        if self.date_format:
            try:
                dt = datetime.strptime(d, self.date_format)
            except:
                raise CastError('Value "%s" does not match date format.' % d)

            return dt.date()

        value, ctx = self.parser.parseDT(d, sourceTime=ZERO_DT)

        if ctx.hasDate and not ctx.hasTime:
            return value.date()

        raise CastError('Can not parse value "%s" as date.' % d)
예제 #6
0
    def cast(self, d):
        """
        Cast a single value to a :class:`decimal.Decimal`.

        :returns:
            :class:`decimal.Decimal` or :code:`None`.
        """
        if isinstance(d, Decimal) or d is None:
            return d

        t = type(d)

        if t is int:
            return Decimal(d)
        elif six.PY2 and t is long:  # noqa: F821
            return Decimal(d)
        elif t is float:
            return Decimal(repr(d))
        elif d is False:
            return Decimal(0)
        elif d is True:
            return Decimal(1)
        elif not isinstance(d, six.string_types):
            raise CastError('Can not parse value "%s" as Decimal.' % d)

        d = d.strip()

        if d.lower() in self.null_values:
            return None

        d = d.strip('%')

        if len(d) > 0 and d[0] == '-':
            d = d[1:]
            sign = NEGATIVE
        else:
            sign = POSITIVE

        for symbol in self.currency_symbols:
            d = d.strip(symbol)

        d = d.replace(self.group_symbol, '')
        d = d.replace(self.decimal_symbol, '.')

        try:
            return Decimal(d) * sign
        # The Decimal class will return an InvalidOperation exception on most Python implementations,
        # but PyPy3 may return a ValueError if the string is not translatable to ASCII
        except (InvalidOperation, ValueError):
            pass

        raise CastError('Can not parse value "%s" as Decimal.' % d)
    def cast(self, d):
        """
        Cast a single value to a :class:`datetime.datetime`.

        :param datetime_format:
            An optional :func:`datetime.strptime` format string for parsing
            datetimes in this column.
        :returns:
            :class:`datetime.datetime` or :code:`None`.
        """
        if isinstance(d, datetime.datetime) or d is None:
            return d
        elif isinstance(d, datetime.date):
            return datetime.datetime.combine(d, datetime.time(0, 0, 0))
        elif isinstance(d, six.string_types):
            d = d.strip()

            if d.lower() in self.null_values:
                return None
        else:
            raise CastError('Can not parse value "%s" as datetime.' % d)

        if self.datetime_format:
            try:
                return datetime.datetime.strptime(d, self.datetime_format)
            except:
                raise CastError('Value "%s" does not match date format.' % d)

        try:
            (_, _, _, _,
             matched_text), = self._parser.nlp(d, sourceTime=self._source_time)
        except:
            matched_text = None
        else:
            value, ctx = self._parser.parseDT(d,
                                              sourceTime=self._source_time,
                                              tzinfo=self.timezone)

            if matched_text == d and ctx.hasDate and ctx.hasTime:
                return value
            elif matched_text == d and ctx.hasDate and not ctx.hasTime:
                return datetime.datetime.combine(value.date(),
                                                 datetime.time.min)

        try:
            dt = isodate.parse_datetime(d)

            return dt
        except:
            pass

        raise CastError('Can not parse value "%s" as datetime.' % d)
예제 #8
0
파일: number.py 프로젝트: doc22940/agate
    def cast(self, d):
        """
        Cast a single value to a :class:`decimal.Decimal`.

        :returns:
            :class:`decimal.Decimal` or :code:`None`.
        """
        if isinstance(d, Decimal) or d is None:
            return d

        t = type(d)

        if t is int:
            return Decimal(d)
        elif six.PY2 and t is long:
            return Decimal(d)
        elif t is float:
            return Decimal(repr(d))
        elif d is False:
            return Decimal(0)
        elif d is True:
            return Decimal(1)
        elif not isinstance(d, six.string_types):
            raise CastError('Can not parse value "%s" as Decimal.' % d)

        d = d.strip()

        if d.lower() in self.null_values:
            return None

        d = d.strip('%')

        if len(d) > 0 and d[0] == '-':
            d = d[1:]
            sign = NEGATIVE
        else:
            sign = POSITIVE

        for symbol in self.currency_symbols:
            d = d.strip(symbol)

        d = d.replace(self.group_symbol, '')
        d = d.replace(self.decimal_symbol, '.')

        try:
            return Decimal(d) * sign
        except InvalidOperation:
            pass

        raise CastError('Can not parse value "%s" as Decimal.' % d)
예제 #9
0
파일: date.py 프로젝트: sandyp/agate
    def cast(self, d):
        """
        Cast a single value to a :class:`datetime.date`.

        :param date_format:
            An optional :func:`datetime.strptime` format string for parsing
            datetimes in this column.
        :returns:
            :class:`datetime.date` or :code:`None`.
        """
        if type(d) is datetime.date or d is None:
            return d
        elif isinstance(d, six.string_types):
            d = d.strip()

            if d.lower() in self.null_values:
                return None
        else:
            raise CastError('Can not parse value "%s" as date.' % d)

        if self.date_format:
            try:
                dt = datetime.datetime.strptime(d, self.date_format)
            except:
                raise CastError('Value "%s" does not match date format.' % d)

            return dt.date()

        zero = datetime.datetime.combine(datetime.date.min, datetime.time.min)

        value, status = self.parser.parseDT(d, sourceTime=zero)

        if status == 1:
            if value.time() != datetime.time.min:
                raise CastError('Value "%s" is datetime, not date.' % d)

            return value.date()

        try:
            dt = isodate.parse_date(d)

            try:
                dt = isodate.parse_datetime(d)
            except:
                return dt
        except:
            pass

        raise CastError('Can not parse value "%s" as date.' % d)
예제 #10
0
    def cast(self, d):
        """
        Cast a single value to :class:`bool`.

        :param d: A value to cast.
        :returns: :class:`bool` or :code:`None`.
        """
        if isinstance(d, bool) or d is None:
            return d

        if isinstance(d, six.string_types):
            d = d.replace(',', '').strip()

            d_lower = d.lower()

            if d_lower in self.null_values:
                return None

            if d_lower in self.true_values:
                return True

            if d_lower in self.false_values:
                return False

        raise CastError('Can not convert value %s to bool for BooleanColumn.' %
                        d)
예제 #11
0
파일: date_time.py 프로젝트: nsonnad/agate
    def cast(self, d):
        """
        Cast a single value to a :class:`datetime.datetime`.

        :param date_format:
            An optional :func:`datetime.strptime` format string for parsing
            datetimes in this column.
        :returns:
            :class:`datetime.datetime` or :code:`None`.
        """
        if isinstance(d, datetime.datetime) or d is None:
            return d
        elif isinstance(d, six.string_types):
            d = d.strip()

            if d.lower() in self.null_values:
                return None

        if self.datetime_format:
            return datetime.datetime.strptime(d, self.datetime_format)

        value, status = self._parser.parseDT(d,
                                             sourceTime=self._source_time,
                                             tzinfo=self.timezone)

        if status != 3:
            raise CastError('Can not parse value "%s" to as datetime.' % d)

        return value
예제 #12
0
파일: boolean.py 프로젝트: sandyp/agate
    def cast(self, d):
        """
        Cast a single value to :class:`bool`.

        :param d: A value to cast.
        :returns: :class:`bool` or :code:`None`.
        """
        if d is None:
            return d
        elif type(d) is bool and type(d) is not int:
            return d
        elif type(d) is int or isinstance(d, Decimal):
            if d == 1:
                return True
            elif d == 0:
                return False
        elif isinstance(d, six.string_types):
            d = d.replace(',', '').strip()

            d_lower = d.lower()

            if d_lower in self.null_values:
                return None
            elif d_lower in self.true_values:
                return True
            elif d_lower in self.false_values:
                return False

        raise CastError('Can not convert value %s to bool.' % d)
예제 #13
0
    def cast(self, d):
        """
        Cast a single value to a :class:`datetime.date`.

        If both `date_format` and `locale` have been specified
        in the `agate.Date` instance, the `cast()` function
        is not thread-safe.
        :returns:
            :class:`datetime.date` or :code:`None`.
        """
        if type(d) is date or d is None:
            return d
        elif isinstance(d, six.string_types):
            d = d.strip()

            if d.lower() in self.null_values:
                return None
        else:
            raise CastError('Can not parse value "%s" as date.' % d)

        if self.date_format:
            orig_locale = None
            if self.locale:
                orig_locale = locale.getlocale(locale.LC_TIME)
                locale.setlocale(locale.LC_TIME, (self.locale, 'UTF-8'))

            try:
                dt = datetime.strptime(d, self.date_format)
            except (ValueError, TypeError):
                raise CastError('Value "%s" does not match date format.' % d)
            finally:
                if orig_locale:
                    locale.setlocale(locale.LC_TIME, orig_locale)

            return dt.date()

        try:
            (value, ctx, _, _,
             matched_text), = self._parser.nlp(d, sourceTime=ZERO_DT)
        except (TypeError, ValueError, OverflowError):
            raise CastError('Value "%s" does not match date format.' % d)
        else:
            if matched_text == d and ctx.hasDate and not ctx.hasTime:
                return value.date()

        raise CastError('Can not parse value "%s" as date.' % d)
예제 #14
0
    def cast(self, d):
        """
        Cast a single value to :code:`None`.

        :param d:
            A value to cast.
        :returns:
            :code:`None`
        """
        if d is None:
            return d

        if self.cast_nulls and isinstance(d, six.string_types):
            if d.strip().lower() in self.null_values:
                return None

        raise CastError('Can not parse value "%s" as Null.' % d)
예제 #15
0
 def cast(self, d):
     if d is None:
         return d
     if re.match(r"^(?:[01]\d|2[0-3]|\d):[0-5]\d$", str(d)):
         return Text().cast(d)
     raise CastError('Can not parse value "%s" as time.' % d)
예제 #16
0
    def cast(self, d):
        """
        Cast a single value to a :class:`datetime.datetime`.

        If both `date_format` and `locale` have been specified
        in the `agate.DateTime` instance, the `cast()` function
        is not thread-safe.
        :returns:
            :class:`datetime.datetime` or :code:`None`.
        """
        if isinstance(d, datetime.datetime) or d is None:
            return d
        elif isinstance(d, datetime.date):
            return datetime.datetime.combine(d, datetime.time(0, 0, 0))
        elif isinstance(d, six.string_types):
            d = d.strip()

            if d.lower() in self.null_values:
                return None
        else:
            raise CastError('Can not parse value "%s" as datetime.' % d)

        if self.datetime_format:
            orig_locale = None
            if self.locale:
                orig_locale = locale.getlocale(locale.LC_TIME)
                locale.setlocale(locale.LC_TIME, (self.locale, 'UTF-8'))

            try:
                dt = datetime.datetime.strptime(d, self.datetime_format)
            except (ValueError, TypeError):
                raise CastError('Value "%s" does not match date format.' % d)
            finally:
                if orig_locale:
                    locale.setlocale(locale.LC_TIME, orig_locale)

            return dt

        try:
            (_, _, _, _,
             matched_text), = self._parser.nlp(d, sourceTime=self._source_time)
        except Exception:
            matched_text = None
        else:
            value, ctx = self._parser.parseDT(d,
                                              sourceTime=self._source_time,
                                              tzinfo=self.timezone)

            if matched_text == d and ctx.hasDate and ctx.hasTime:
                return value
            elif matched_text == d and ctx.hasDate and not ctx.hasTime:
                return datetime.datetime.combine(value.date(),
                                                 datetime.time.min)

        try:
            dt = isodate.parse_datetime(d)

            return dt
        except Exception:
            pass

        raise CastError('Can not parse value "%s" as datetime.' % d)
예제 #17
0
 def cast(self, d):
     if d is None:
         return d
     if is_valid_siret(d) or is_valid_siren(d):
         return Text().cast(d)
     raise CastError('Can not parse value "%s" as a SIREN or SIRET.' % d)
예제 #18
0
    def __init__(self,
                 rows,
                 column_names=None,
                 column_types=None,
                 row_names=None,
                 _is_fork=False):
        if isinstance(rows, six.string_types):
            raise ValueError(
                'When created directly, the first argument to Table must be a sequence of rows. Did you want agate.Table.from_csv?'
            )

        # Validate column names
        if column_names:
            final_column_names = []

            for i, column_name in enumerate(column_names):
                if not column_name:
                    new_column_name = utils.letter_name(i)
                    warn_unnamed_column(i, new_column_name)
                elif isinstance(column_name, six.string_types):
                    new_column_name = column_name
                else:
                    raise ValueError('Column names must be strings or None.')

                final_column_name = new_column_name
                duplicates = 0

                while final_column_name in final_column_names:
                    final_column_name = new_column_name + '_' + str(
                        duplicates + 2)
                    duplicates += 1

                if duplicates > 0:
                    warn_duplicate_column(new_column_name, final_column_name)

                final_column_names.append(final_column_name)

            self._column_names = tuple(final_column_names)
        elif rows:
            self._column_names = tuple(
                utils.letter_name(i) for i in range(len(rows[0])))
            warnings.warn(
                'Column names not specified. "%s" will be used as names.' %
                str(self._column_names),
                RuntimeWarning,
                stacklevel=2)
        else:
            self._column_names = tuple()

        len_column_names = len(self._column_names)

        # Validate column_types
        if column_types is None:
            column_types = TypeTester()
        elif isinstance(column_types, dict):
            for v in column_types.values():
                if not isinstance(v, DataType):
                    raise ValueError(
                        'Column types must be instances of DataType.')

            column_types = TypeTester(force=column_types)
        elif not isinstance(column_types, TypeTester):
            for column_type in column_types:
                if not isinstance(column_type, DataType):
                    raise ValueError(
                        'Column types must be instances of DataType.')

        if isinstance(column_types, TypeTester):
            self._column_types = column_types.run(rows, self._column_names)
        else:
            self._column_types = tuple(column_types)

        if len_column_names != len(self._column_types):
            raise ValueError(
                'column_names and column_types must be the same length.')

        if not _is_fork:
            new_rows = []
            cast_funcs = [c.cast for c in self._column_types]

            for i, row in enumerate(rows):
                len_row = len(row)

                if len_row > len_column_names:
                    raise ValueError(
                        'Row %i has %i values, but Table only has %i columns.'
                        % (i, len_row, len_column_names))
                elif len(row) < len_column_names:
                    row = chain(row, [None] * (len_column_names - len_row))

                row_values = []
                for j, d in enumerate(row):
                    try:
                        row_values.append(cast_funcs[j](d))
                    except CastError as e:
                        raise CastError(
                            str(e) + ' Error at row %s column %s.' %
                            (i, self._column_names[j]))

                new_rows.append(Row(row_values, self._column_names))
        else:
            new_rows = rows

        if row_names:
            computed_row_names = []

            if isinstance(row_names, six.string_types):
                for row in new_rows:
                    name = row[row_names]
                    computed_row_names.append(name)
            elif hasattr(row_names, '__call__'):
                for row in new_rows:
                    name = row_names(row)
                    computed_row_names.append(name)
            elif utils.issequence(row_names):
                computed_row_names = row_names
            else:
                raise ValueError(
                    'row_names must be a column name, function or sequence')

            for row_name in computed_row_names:
                if type(row_name) is int:
                    raise ValueError(
                        'Row names cannot be of type int. Use Decimal for numbered row names.'
                    )

            self._row_names = tuple(computed_row_names)
        else:
            self._row_names = None

        self._rows = MappedSequence(new_rows, self._row_names)

        # Build columns
        new_columns = []

        for i in range(len_column_names):
            name = self._column_names[i]
            data_type = self._column_types[i]

            column = Column(i,
                            name,
                            data_type,
                            self._rows,
                            row_names=self._row_names)

            new_columns.append(column)

        self._columns = MappedSequence(new_columns, self._column_names)