summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/cyextension/processors.pyx
diff options
context:
space:
mode:
authorFederico Caselli <cfederico87@gmail.com>2021-01-01 16:09:01 +0100
committerFederico Caselli <cfederico87@gmail.com>2021-12-17 21:29:05 +0100
commit76fa211620de167b76846f0e5db5b64b8756ad48 (patch)
treec435dbf6585b3758dc78ee82bf114e162a25d0e1 /lib/sqlalchemy/cyextension/processors.pyx
parent3543fcc9c9601e81560d055ceadaea05c75815c0 (diff)
downloadsqlalchemy-workflow_test_cython.tar.gz
Replace c extension with cython versions.workflow_test_cython
Re-implement c version immutabledict / processors / resultproxy / utils with cython. Performance is in general in par or better than the c version Added a collection module that has cython version of OrderedSet and IdentitySet Added a new test/perf file to compare the implementations. Run ``python test/perf/compiled_extensions.py all`` to execute the comparison test. See results here: https://docs.google.com/document/d/1nOcDGojHRtXEkuy4vNXcW_XOJd9gqKhSeALGG3kYr6A/edit?usp=sharing Fixes: #7256 Change-Id: I2930ef1894b5048210384728118e586e813f6a76 Signed-off-by: Federico Caselli <cfederico87@gmail.com>
Diffstat (limited to 'lib/sqlalchemy/cyextension/processors.pyx')
-rw-r--r--lib/sqlalchemy/cyextension/processors.pyx91
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, &microsecond)
+ 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, &microsecond)
+ 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)