/pypy/module/cpyext/cdatetime.py

https://github.com/alemacgo/pypy · Python · 249 lines · 164 code · 38 blank · 47 comment · 4 complexity · 344205b8172d2b766bc31aea67ba3697 MD5 · raw file

  1. from pypy.rpython.lltypesystem import rffi, lltype
  2. from pypy.module.cpyext.pyobject import PyObject, make_ref
  3. from pypy.module.cpyext.api import (cpython_api, CANNOT_FAIL, cpython_struct,
  4. PyObjectFields)
  5. from pypy.module.cpyext.import_ import PyImport_Import
  6. from pypy.module.cpyext.typeobject import PyTypeObjectPtr
  7. from pypy.interpreter.error import OperationError
  8. from pypy.tool.sourcetools import func_renamer
  9. # API import function
  10. PyDateTime_CAPI = cpython_struct(
  11. 'PyDateTime_CAPI',
  12. (('DateType', PyTypeObjectPtr),
  13. ('DateTimeType', PyTypeObjectPtr),
  14. ('TimeType', PyTypeObjectPtr),
  15. ('DeltaType', PyTypeObjectPtr),
  16. ))
  17. @cpython_api([], lltype.Ptr(PyDateTime_CAPI))
  18. def _PyDateTime_Import(space):
  19. datetimeAPI = lltype.malloc(PyDateTime_CAPI, flavor='raw',
  20. track_allocation=False)
  21. w_datetime = PyImport_Import(space, space.wrap("datetime"))
  22. w_type = space.getattr(w_datetime, space.wrap("date"))
  23. datetimeAPI.c_DateType = rffi.cast(
  24. PyTypeObjectPtr, make_ref(space, w_type))
  25. w_type = space.getattr(w_datetime, space.wrap("datetime"))
  26. datetimeAPI.c_DateTimeType = rffi.cast(
  27. PyTypeObjectPtr, make_ref(space, w_type))
  28. w_type = space.getattr(w_datetime, space.wrap("time"))
  29. datetimeAPI.c_TimeType = rffi.cast(
  30. PyTypeObjectPtr, make_ref(space, w_type))
  31. w_type = space.getattr(w_datetime, space.wrap("timedelta"))
  32. datetimeAPI.c_DeltaType = rffi.cast(
  33. PyTypeObjectPtr, make_ref(space, w_type))
  34. return datetimeAPI
  35. PyDateTime_Date = PyObject
  36. PyDateTime_Time = PyObject
  37. PyDateTime_DateTime = PyObject
  38. PyDeltaObjectStruct = lltype.ForwardReference()
  39. cpython_struct("PyDateTime_Delta", PyObjectFields, PyDeltaObjectStruct)
  40. PyDateTime_Delta = lltype.Ptr(PyDeltaObjectStruct)
  41. # Check functions
  42. def make_check_function(func_name, type_name):
  43. @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
  44. @func_renamer(func_name)
  45. def check(space, w_obj):
  46. try:
  47. return space.is_true(
  48. space.appexec([w_obj], """(obj):
  49. from datetime import %s as datatype
  50. return isinstance(obj, datatype)
  51. """ % (type_name,)))
  52. except OperationError:
  53. return 0
  54. @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
  55. @func_renamer(func_name + "Exact")
  56. def check_exact(space, w_obj):
  57. try:
  58. return space.is_true(
  59. space.appexec([w_obj], """(obj):
  60. from datetime import %s as datatype
  61. return type(obj) is datatype
  62. """ % (type_name,)))
  63. except OperationError:
  64. return 0
  65. make_check_function("PyDateTime_Check", "datetime")
  66. make_check_function("PyDate_Check", "date")
  67. make_check_function("PyTime_Check", "time")
  68. make_check_function("PyDelta_Check", "timedelta")
  69. # Constructors
  70. @cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject)
  71. def PyDate_FromDate(space, year, month, day):
  72. """Return a datetime.date object with the specified year, month and day.
  73. """
  74. year = rffi.cast(lltype.Signed, year)
  75. month = rffi.cast(lltype.Signed, month)
  76. day = rffi.cast(lltype.Signed, day)
  77. w_datetime = PyImport_Import(space, space.wrap("datetime"))
  78. return space.call_method(
  79. w_datetime, "date",
  80. space.wrap(year), space.wrap(month), space.wrap(day))
  81. @cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject)
  82. def PyTime_FromTime(space, hour, minute, second, usecond):
  83. """Return a ``datetime.time`` object with the specified hour, minute, second and
  84. microsecond."""
  85. hour = rffi.cast(lltype.Signed, hour)
  86. minute = rffi.cast(lltype.Signed, minute)
  87. second = rffi.cast(lltype.Signed, second)
  88. usecond = rffi.cast(lltype.Signed, usecond)
  89. w_datetime = PyImport_Import(space, space.wrap("datetime"))
  90. return space.call_method(
  91. w_datetime, "time",
  92. space.wrap(hour), space.wrap(minute), space.wrap(second),
  93. space.wrap(usecond))
  94. @cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject)
  95. def PyDateTime_FromDateAndTime(space, year, month, day, hour, minute, second, usecond):
  96. """Return a datetime.datetime object with the specified year, month, day, hour,
  97. minute, second and microsecond.
  98. """
  99. year = rffi.cast(lltype.Signed, year)
  100. month = rffi.cast(lltype.Signed, month)
  101. day = rffi.cast(lltype.Signed, day)
  102. hour = rffi.cast(lltype.Signed, hour)
  103. minute = rffi.cast(lltype.Signed, minute)
  104. second = rffi.cast(lltype.Signed, second)
  105. usecond = rffi.cast(lltype.Signed, usecond)
  106. w_datetime = PyImport_Import(space, space.wrap("datetime"))
  107. return space.call_method(
  108. w_datetime, "datetime",
  109. space.wrap(year), space.wrap(month), space.wrap(day),
  110. space.wrap(hour), space.wrap(minute), space.wrap(second),
  111. space.wrap(usecond))
  112. @cpython_api([PyObject], PyObject)
  113. def PyDateTime_FromTimestamp(space, w_args):
  114. """Create and return a new datetime.datetime object given an argument tuple
  115. suitable for passing to datetime.datetime.fromtimestamp().
  116. """
  117. w_datetime = PyImport_Import(space, space.wrap("datetime"))
  118. w_type = space.getattr(w_datetime, space.wrap("datetime"))
  119. w_method = space.getattr(w_type, space.wrap("fromtimestamp"))
  120. return space.call(w_method, w_args)
  121. @cpython_api([PyObject], PyObject)
  122. def PyDate_FromTimestamp(space, w_args):
  123. """Create and return a new datetime.date object given an argument tuple
  124. suitable for passing to datetime.date.fromtimestamp().
  125. """
  126. w_datetime = PyImport_Import(space, space.wrap("datetime"))
  127. w_type = space.getattr(w_datetime, space.wrap("date"))
  128. w_method = space.getattr(w_type, space.wrap("fromtimestamp"))
  129. return space.call(w_method, w_args)
  130. @cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject)
  131. def PyDelta_FromDSU(space, days, seconds, useconds):
  132. """Return a datetime.timedelta object representing the given number of days,
  133. seconds and microseconds. Normalization is performed so that the resulting
  134. number of microseconds and seconds lie in the ranges documented for
  135. datetime.timedelta objects.
  136. """
  137. days = rffi.cast(lltype.Signed, days)
  138. seconds = rffi.cast(lltype.Signed, seconds)
  139. useconds = rffi.cast(lltype.Signed, useconds)
  140. w_datetime = PyImport_Import(space, space.wrap("datetime"))
  141. return space.call_method(
  142. w_datetime, "timedelta",
  143. space.wrap(days), space.wrap(seconds), space.wrap(useconds))
  144. # Accessors
  145. @cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL)
  146. def PyDateTime_GET_YEAR(space, w_obj):
  147. """Return the year, as a positive int.
  148. """
  149. return space.int_w(space.getattr(w_obj, space.wrap("year")))
  150. @cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL)
  151. def PyDateTime_GET_MONTH(space, w_obj):
  152. """Return the month, as an int from 1 through 12.
  153. """
  154. return space.int_w(space.getattr(w_obj, space.wrap("month")))
  155. @cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL)
  156. def PyDateTime_GET_DAY(space, w_obj):
  157. """Return the day, as an int from 1 through 31.
  158. """
  159. return space.int_w(space.getattr(w_obj, space.wrap("day")))
  160. @cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL)
  161. def PyDateTime_DATE_GET_HOUR(space, w_obj):
  162. """Return the hour, as an int from 0 through 23.
  163. """
  164. return space.int_w(space.getattr(w_obj, space.wrap("hour")))
  165. @cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL)
  166. def PyDateTime_DATE_GET_MINUTE(space, w_obj):
  167. """Return the minute, as an int from 0 through 59.
  168. """
  169. return space.int_w(space.getattr(w_obj, space.wrap("minute")))
  170. @cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL)
  171. def PyDateTime_DATE_GET_SECOND(space, w_obj):
  172. """Return the second, as an int from 0 through 59.
  173. """
  174. return space.int_w(space.getattr(w_obj, space.wrap("second")))
  175. @cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL)
  176. def PyDateTime_DATE_GET_MICROSECOND(space, w_obj):
  177. """Return the microsecond, as an int from 0 through 999999.
  178. """
  179. return space.int_w(space.getattr(w_obj, space.wrap("microsecond")))
  180. @cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL)
  181. def PyDateTime_TIME_GET_HOUR(space, w_obj):
  182. """Return the hour, as an int from 0 through 23.
  183. """
  184. return space.int_w(space.getattr(w_obj, space.wrap("hour")))
  185. @cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL)
  186. def PyDateTime_TIME_GET_MINUTE(space, w_obj):
  187. """Return the minute, as an int from 0 through 59.
  188. """
  189. return space.int_w(space.getattr(w_obj, space.wrap("minute")))
  190. @cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL)
  191. def PyDateTime_TIME_GET_SECOND(space, w_obj):
  192. """Return the second, as an int from 0 through 59.
  193. """
  194. return space.int_w(space.getattr(w_obj, space.wrap("second")))
  195. @cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL)
  196. def PyDateTime_TIME_GET_MICROSECOND(space, w_obj):
  197. """Return the microsecond, as an int from 0 through 999999.
  198. """
  199. return space.int_w(space.getattr(w_obj, space.wrap("microsecond")))
  200. # XXX these functions are not present in the Python API
  201. # But it does not seem possible to expose a different structure
  202. # for types defined in a python module like lib/datetime.py.
  203. @cpython_api([PyDateTime_Delta], rffi.INT_real, error=CANNOT_FAIL)
  204. def PyDateTime_DELTA_GET_DAYS(space, w_obj):
  205. return space.int_w(space.getattr(w_obj, space.wrap("days")))
  206. @cpython_api([PyDateTime_Delta], rffi.INT_real, error=CANNOT_FAIL)
  207. def PyDateTime_DELTA_GET_SECONDS(space, w_obj):
  208. return space.int_w(space.getattr(w_obj, space.wrap("seconds")))
  209. @cpython_api([PyDateTime_Delta], rffi.INT_real, error=CANNOT_FAIL)
  210. def PyDateTime_DELTA_GET_MICROSECONDS(space, w_obj):
  211. return space.int_w(space.getattr(w_obj, space.wrap("microseconds")))