PageRenderTime 43ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/pypy/module/cpyext/cdatetime.py

https://bitbucket.org/pypy/pypy/
Python | 296 lines | 278 code | 16 blank | 2 comment | 1 complexity | b152ebe5f33a076a371d7bf75fc81f5e MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. from rpython.rtyper.lltypesystem import rffi, lltype
  2. from rpython.rtyper.annlowlevel import llhelper
  3. from pypy.module.cpyext.pyobject import PyObject, make_ref
  4. from pypy.module.cpyext.api import (cpython_api, CANNOT_FAIL, cpython_struct,
  5. PyObjectFields)
  6. from pypy.module.cpyext.import_ import PyImport_Import
  7. from pypy.module.cpyext.typeobject import PyTypeObjectPtr
  8. from pypy.interpreter.error import OperationError
  9. from rpython.tool.sourcetools import func_renamer
  10. # API import function
  11. PyDateTime_CAPI = cpython_struct(
  12. 'PyDateTime_CAPI',
  13. (('DateType', PyTypeObjectPtr),
  14. ('DateTimeType', PyTypeObjectPtr),
  15. ('TimeType', PyTypeObjectPtr),
  16. ('DeltaType', PyTypeObjectPtr),
  17. ('TZInfoType', PyTypeObjectPtr),
  18. ('Date_FromDate', lltype.Ptr(lltype.FuncType(
  19. [rffi.INT_real, rffi.INT_real, rffi.INT_real, PyTypeObjectPtr],
  20. PyObject))),
  21. ('Time_FromTime', lltype.Ptr(lltype.FuncType(
  22. [rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real,
  23. PyObject, PyTypeObjectPtr],
  24. PyObject))),
  25. ('DateTime_FromDateAndTime', lltype.Ptr(lltype.FuncType(
  26. [rffi.INT_real, rffi.INT_real, rffi.INT_real,
  27. rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real,
  28. PyObject, PyTypeObjectPtr],
  29. PyObject))),
  30. ('Delta_FromDelta', lltype.Ptr(lltype.FuncType(
  31. [rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real,
  32. PyTypeObjectPtr],
  33. PyObject))),
  34. ))
  35. @cpython_api([], lltype.Ptr(PyDateTime_CAPI))
  36. def _PyDateTime_Import(space):
  37. datetimeAPI = lltype.malloc(PyDateTime_CAPI, flavor='raw',
  38. track_allocation=False)
  39. w_datetime = PyImport_Import(space, space.wrap("datetime"))
  40. w_type = space.getattr(w_datetime, space.wrap("date"))
  41. datetimeAPI.c_DateType = rffi.cast(
  42. PyTypeObjectPtr, make_ref(space, w_type))
  43. w_type = space.getattr(w_datetime, space.wrap("datetime"))
  44. datetimeAPI.c_DateTimeType = rffi.cast(
  45. PyTypeObjectPtr, make_ref(space, w_type))
  46. w_type = space.getattr(w_datetime, space.wrap("time"))
  47. datetimeAPI.c_TimeType = rffi.cast(
  48. PyTypeObjectPtr, make_ref(space, w_type))
  49. w_type = space.getattr(w_datetime, space.wrap("timedelta"))
  50. datetimeAPI.c_DeltaType = rffi.cast(
  51. PyTypeObjectPtr, make_ref(space, w_type))
  52. w_type = space.getattr(w_datetime, space.wrap("tzinfo"))
  53. datetimeAPI.c_TZInfoType = rffi.cast(
  54. PyTypeObjectPtr, make_ref(space, w_type))
  55. datetimeAPI.c_Date_FromDate = llhelper(
  56. _PyDate_FromDate.api_func.functype,
  57. _PyDate_FromDate.api_func.get_wrapper(space))
  58. datetimeAPI.c_Time_FromTime = llhelper(
  59. _PyTime_FromTime.api_func.functype,
  60. _PyTime_FromTime.api_func.get_wrapper(space))
  61. datetimeAPI.c_DateTime_FromDateAndTime = llhelper(
  62. _PyDateTime_FromDateAndTime.api_func.functype,
  63. _PyDateTime_FromDateAndTime.api_func.get_wrapper(space))
  64. datetimeAPI.c_Delta_FromDelta = llhelper(
  65. _PyDelta_FromDelta.api_func.functype,
  66. _PyDelta_FromDelta.api_func.get_wrapper(space))
  67. return datetimeAPI
  68. PyDateTime_DateStruct = lltype.ForwardReference()
  69. PyDateTime_TimeStruct = lltype.ForwardReference()
  70. PyDateTime_DateTimeStruct = lltype.ForwardReference()
  71. cpython_struct("PyDateTime_Date", PyObjectFields, PyDateTime_DateStruct)
  72. PyDateTime_Date = lltype.Ptr(PyDateTime_DateStruct)
  73. cpython_struct("PyDateTime_Time", PyObjectFields, PyDateTime_TimeStruct)
  74. PyDateTime_Time = lltype.Ptr(PyDateTime_TimeStruct)
  75. cpython_struct("PyDateTime_DateTime", PyObjectFields, PyDateTime_DateTimeStruct)
  76. PyDateTime_DateTime = lltype.Ptr(PyDateTime_DateTimeStruct)
  77. PyDeltaObjectStruct = lltype.ForwardReference()
  78. cpython_struct("PyDateTime_Delta", PyObjectFields, PyDeltaObjectStruct)
  79. PyDateTime_Delta = lltype.Ptr(PyDeltaObjectStruct)
  80. # Check functions
  81. def make_check_function(func_name, type_name):
  82. @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
  83. @func_renamer(func_name)
  84. def check(space, w_obj):
  85. try:
  86. return space.is_true(
  87. space.appexec([w_obj], """(obj):
  88. from datetime import %s as datatype
  89. return isinstance(obj, datatype)
  90. """ % (type_name,)))
  91. except OperationError:
  92. return 0
  93. @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
  94. @func_renamer(func_name + "Exact")
  95. def check_exact(space, w_obj):
  96. try:
  97. return space.is_true(
  98. space.appexec([w_obj], """(obj):
  99. from datetime import %s as datatype
  100. return type(obj) is datatype
  101. """ % (type_name,)))
  102. except OperationError:
  103. return 0
  104. make_check_function("PyDateTime_Check", "datetime")
  105. make_check_function("PyDate_Check", "date")
  106. make_check_function("PyTime_Check", "time")
  107. make_check_function("PyDelta_Check", "timedelta")
  108. make_check_function("PyTZInfo_Check", "tzinfo")
  109. # Constructors. They are better used as macros.
  110. @cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, PyTypeObjectPtr],
  111. PyObject)
  112. def _PyDate_FromDate(space, year, month, day, w_type):
  113. """Return a datetime.date object with the specified year, month and day.
  114. """
  115. year = rffi.cast(lltype.Signed, year)
  116. month = rffi.cast(lltype.Signed, month)
  117. day = rffi.cast(lltype.Signed, day)
  118. return space.call_function(
  119. w_type,
  120. space.wrap(year), space.wrap(month), space.wrap(day))
  121. @cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real,
  122. PyObject, PyTypeObjectPtr], PyObject)
  123. def _PyTime_FromTime(space, hour, minute, second, usecond, w_tzinfo, w_type):
  124. """Return a ``datetime.time`` object with the specified hour, minute, second and
  125. microsecond."""
  126. hour = rffi.cast(lltype.Signed, hour)
  127. minute = rffi.cast(lltype.Signed, minute)
  128. second = rffi.cast(lltype.Signed, second)
  129. usecond = rffi.cast(lltype.Signed, usecond)
  130. return space.call_function(
  131. w_type,
  132. space.wrap(hour), space.wrap(minute), space.wrap(second),
  133. space.wrap(usecond), w_tzinfo)
  134. @cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real,
  135. rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real,
  136. PyObject, PyTypeObjectPtr], PyObject)
  137. def _PyDateTime_FromDateAndTime(space, year, month, day,
  138. hour, minute, second, usecond,
  139. w_tzinfo, w_type):
  140. """Return a datetime.datetime object with the specified year, month, day, hour,
  141. minute, second and microsecond.
  142. """
  143. year = rffi.cast(lltype.Signed, year)
  144. month = rffi.cast(lltype.Signed, month)
  145. day = rffi.cast(lltype.Signed, day)
  146. hour = rffi.cast(lltype.Signed, hour)
  147. minute = rffi.cast(lltype.Signed, minute)
  148. second = rffi.cast(lltype.Signed, second)
  149. usecond = rffi.cast(lltype.Signed, usecond)
  150. return space.call_function(
  151. w_type,
  152. space.wrap(year), space.wrap(month), space.wrap(day),
  153. space.wrap(hour), space.wrap(minute), space.wrap(second),
  154. space.wrap(usecond), w_tzinfo)
  155. @cpython_api([PyObject], PyObject)
  156. def PyDateTime_FromTimestamp(space, w_args):
  157. """Create and return a new datetime.datetime object given an argument tuple
  158. suitable for passing to datetime.datetime.fromtimestamp().
  159. """
  160. w_datetime = PyImport_Import(space, space.wrap("datetime"))
  161. w_type = space.getattr(w_datetime, space.wrap("datetime"))
  162. w_method = space.getattr(w_type, space.wrap("fromtimestamp"))
  163. return space.call(w_method, w_args)
  164. @cpython_api([PyObject], PyObject)
  165. def PyDate_FromTimestamp(space, w_args):
  166. """Create and return a new datetime.date object given an argument tuple
  167. suitable for passing to datetime.date.fromtimestamp().
  168. """
  169. w_datetime = PyImport_Import(space, space.wrap("datetime"))
  170. w_type = space.getattr(w_datetime, space.wrap("date"))
  171. w_method = space.getattr(w_type, space.wrap("fromtimestamp"))
  172. return space.call(w_method, w_args)
  173. @cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real,
  174. PyTypeObjectPtr],
  175. PyObject)
  176. def _PyDelta_FromDelta(space, days, seconds, useconds, normalize, w_type):
  177. """Return a datetime.timedelta object representing the given number of days,
  178. seconds and microseconds. Normalization is performed so that the resulting
  179. number of microseconds and seconds lie in the ranges documented for
  180. datetime.timedelta objects.
  181. """
  182. days = rffi.cast(lltype.Signed, days)
  183. seconds = rffi.cast(lltype.Signed, seconds)
  184. useconds = rffi.cast(lltype.Signed, useconds)
  185. return space.call_function(
  186. w_type,
  187. space.wrap(days), space.wrap(seconds), space.wrap(useconds))
  188. # Accessors
  189. @cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
  190. def PyDateTime_GET_YEAR(space, w_obj):
  191. """Return the year, as a positive int.
  192. """
  193. return space.int_w(space.getattr(w_obj, space.wrap("year")))
  194. @cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
  195. def PyDateTime_GET_MONTH(space, w_obj):
  196. """Return the month, as an int from 1 through 12.
  197. """
  198. return space.int_w(space.getattr(w_obj, space.wrap("month")))
  199. @cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
  200. def PyDateTime_GET_DAY(space, w_obj):
  201. """Return the day, as an int from 1 through 31.
  202. """
  203. return space.int_w(space.getattr(w_obj, space.wrap("day")))
  204. @cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
  205. def PyDateTime_DATE_GET_HOUR(space, w_obj):
  206. """Return the hour, as an int from 0 through 23.
  207. """
  208. return space.int_w(space.getattr(w_obj, space.wrap("hour")))
  209. @cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
  210. def PyDateTime_DATE_GET_MINUTE(space, w_obj):
  211. """Return the minute, as an int from 0 through 59.
  212. """
  213. return space.int_w(space.getattr(w_obj, space.wrap("minute")))
  214. @cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
  215. def PyDateTime_DATE_GET_SECOND(space, w_obj):
  216. """Return the second, as an int from 0 through 59.
  217. """
  218. return space.int_w(space.getattr(w_obj, space.wrap("second")))
  219. @cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
  220. def PyDateTime_DATE_GET_MICROSECOND(space, w_obj):
  221. """Return the microsecond, as an int from 0 through 999999.
  222. """
  223. return space.int_w(space.getattr(w_obj, space.wrap("microsecond")))
  224. @cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
  225. def PyDateTime_TIME_GET_HOUR(space, w_obj):
  226. """Return the hour, as an int from 0 through 23.
  227. """
  228. return space.int_w(space.getattr(w_obj, space.wrap("hour")))
  229. @cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
  230. def PyDateTime_TIME_GET_MINUTE(space, w_obj):
  231. """Return the minute, as an int from 0 through 59.
  232. """
  233. return space.int_w(space.getattr(w_obj, space.wrap("minute")))
  234. @cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
  235. def PyDateTime_TIME_GET_SECOND(space, w_obj):
  236. """Return the second, as an int from 0 through 59.
  237. """
  238. return space.int_w(space.getattr(w_obj, space.wrap("second")))
  239. @cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
  240. def PyDateTime_TIME_GET_MICROSECOND(space, w_obj):
  241. """Return the microsecond, as an int from 0 through 999999.
  242. """
  243. return space.int_w(space.getattr(w_obj, space.wrap("microsecond")))
  244. # XXX these functions are not present in the Python API
  245. # But it does not seem possible to expose a different structure
  246. # for types defined in a python module like lib/datetime.py.
  247. @cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
  248. def PyDateTime_DELTA_GET_DAYS(space, w_obj):
  249. return space.int_w(space.getattr(w_obj, space.wrap("days")))
  250. @cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
  251. def PyDateTime_DELTA_GET_SECONDS(space, w_obj):
  252. return space.int_w(space.getattr(w_obj, space.wrap("seconds")))
  253. @cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
  254. def PyDateTime_DELTA_GET_MICROSECONDS(space, w_obj):
  255. return space.int_w(space.getattr(w_obj, space.wrap("microseconds")))