diff options
Diffstat (limited to 'lib/sqlalchemy/cyextension/processors.pyx')
-rw-r--r-- | lib/sqlalchemy/cyextension/processors.pyx | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/lib/sqlalchemy/cyextension/processors.pyx b/lib/sqlalchemy/cyextension/processors.pyx new file mode 100644 index 000000000..9f23e73b1 --- /dev/null +++ b/lib/sqlalchemy/cyextension/processors.pyx @@ -0,0 +1,91 @@ +import datetime +import re + +from cpython.datetime cimport date_new, datetime_new, import_datetime, time_new +from cpython.object cimport PyObject_Str +from cpython.unicode cimport PyUnicode_AsASCIIString, PyUnicode_Check, PyUnicode_Decode +from libc.stdio cimport sscanf + + +def int_to_boolean(value): + if value is None: + return None + return True if value else False + +def to_str(value): + return PyObject_Str(value) if value is not None else None + +def to_float(value): + return float(value) if value is not None else None + +cdef inline bytes to_bytes(object value, str type_name): + try: + return PyUnicode_AsASCIIString(value) + except Exception as e: + raise ValueError( + f"Couldn't parse {type_name} string '{value!r}' " + "- value is not a string." + ) from e + +import_datetime() # required to call datetime_new/date_new/time_new + +def str_to_datetime(value): + if value is None: + return None + cdef int numparsed + cdef unsigned int year, month, day, hour, minute, second, microsecond = 0 + cdef bytes value_b = to_bytes(value, 'datetime') + cdef const char * string = value_b + + numparsed = sscanf(string, "%4u-%2u-%2u %2u:%2u:%2u.%6u", + &year, &month, &day, &hour, &minute, &second, µsecond) + if numparsed < 6: + raise ValueError( + "Couldn't parse datetime string: '%s'" % (value) + ) + return datetime_new(year, month, day, hour, minute, second, microsecond, None) + +def str_to_date(value): + if value is None: + return None + cdef int numparsed + cdef unsigned int year, month, day + cdef bytes value_b = to_bytes(value, 'date') + cdef const char * string = value_b + + numparsed = sscanf(string, "%4u-%2u-%2u", &year, &month, &day) + if numparsed != 3: + raise ValueError( + "Couldn't parse date string: '%s'" % (value) + ) + return date_new(year, month, day) + +def str_to_time(value): + if value is None: + return None + cdef int numparsed + cdef unsigned int hour, minute, second, microsecond = 0 + cdef bytes value_b = to_bytes(value, 'time') + cdef const char * string = value_b + + numparsed = sscanf(string, "%2u:%2u:%2u.%6u", &hour, &minute, &second, µsecond) + if numparsed < 3: + raise ValueError( + "Couldn't parse time string: '%s'" % (value) + ) + return time_new(hour, minute, second, microsecond, None) + + +cdef class DecimalResultProcessor: + cdef object type_ + cdef str format_ + + def __cinit__(self, type_, format_): + self.type_ = type_ + self.format_ = format_ + + def process(self, object value): + if value is None: + return None + else: + return self.type_(self.format_ % value) |