[pypy-commit] pypy cpyext-datetime2: create interp classes to hold the tzinfo field, hack till tests pass and translates
mattip
pypy.commits at gmail.com
Thu Jan 18 02:07:37 EST 2018
Author: Matti Picus <matti.picus at gmail.com>
Branch: cpyext-datetime2
Changeset: r93679:e3d98c733d8b
Date: 2018-01-17 23:17 +0200
http://bitbucket.org/pypy/pypy/changeset/e3d98c733d8b/
Log: create interp classes to hold the tzinfo field, hack till tests pass
and translates
diff --git a/lib_pypy/datetime.py b/lib_pypy/datetime.py
--- a/lib_pypy/datetime.py
+++ b/lib_pypy/datetime.py
@@ -17,10 +17,13 @@
"""
from __future__ import division
-import time as _time
+import time as _timemodule
import math as _math
import struct as _struct
+# for cpyext, use these as base classes
+from __pypy__._pypydatetime import dateinterop, deltainterop, timeinterop
+
_SENTINEL = object()
def _cmp(x, y):
@@ -179,7 +182,7 @@
def _build_struct_time(y, m, d, hh, mm, ss, dstflag):
wday = (_ymd2ord(y, m, d) + 6) % 7
dnum = _days_before_month(y, m) + d
- return _time.struct_time((y, m, d, hh, mm, ss, wday, dnum, dstflag))
+ return _timemodule.struct_time((y, m, d, hh, mm, ss, wday, dnum, dstflag))
def _format_time(hh, mm, ss, us):
# Skip trailing microseconds when us==0.
@@ -247,7 +250,7 @@
else:
push(ch)
newformat = "".join(newformat)
- return _time.strftime(newformat, timetuple)
+ return _timemodule.strftime(newformat, timetuple)
# Just raise TypeError if the arg isn't None or a string.
def _check_tzname(name):
@@ -433,7 +436,7 @@
raise TypeError("unsupported type for timedelta %s component: %s" %
(tag, type(num)))
-class timedelta(object):
+class timedelta(deltainterop):
"""Represent the difference between two datetime objects.
Supported operators:
@@ -489,7 +492,7 @@
if not -_MAX_DELTA_DAYS <= d <= _MAX_DELTA_DAYS:
raise OverflowError("days=%d; must have magnitude <= %d" % (d, _MAX_DELTA_DAYS))
- self = object.__new__(cls)
+ self = deltainterop.__new__(cls)
self._days = d
self._seconds = s
self._microseconds = us
@@ -667,7 +670,7 @@
timedelta.max = timedelta(_MAX_DELTA_DAYS, 24*3600-1, 1000000-1)
timedelta.resolution = timedelta(microseconds=1)
-class date(object):
+class date(dateinterop):
"""Concrete date type.
Constructors:
@@ -707,12 +710,12 @@
if month is None and isinstance(year, bytes) and len(year) == 4 and \
1 <= ord(year[2]) <= 12:
# Pickle support
- self = object.__new__(cls)
+ self = dateinterop.__new__(cls)
self.__setstate(year)
self._hashcode = -1
return self
year, month, day = _check_date_fields(year, month, day)
- self = object.__new__(cls)
+ self = dateinterop.__new__(cls)
self._year = year
self._month = month
self._day = day
@@ -724,13 +727,13 @@
@classmethod
def fromtimestamp(cls, t):
"Construct a date from a POSIX timestamp (like time.time())."
- y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t)
+ y, m, d, hh, mm, ss, weekday, jday, dst = _timemodule.localtime(t)
return cls(y, m, d)
@classmethod
def today(cls):
"Construct a date from time.time()."
- t = _time.time()
+ t = _timemodule.time()
return cls.fromtimestamp(t)
@classmethod
@@ -1061,7 +1064,7 @@
_tzinfo_class = tzinfo
-class time(object):
+class time(timeinterop):
"""Time with time zone.
Constructors:
@@ -1097,14 +1100,14 @@
"""
if isinstance(hour, bytes) and len(hour) == 6 and ord(hour[0]) < 24:
# Pickle support
- self = object.__new__(cls)
+ self = timeinterop.__new__(cls)
self.__setstate(hour, minute or None)
self._hashcode = -1
return self
hour, minute, second, microsecond = _check_time_fields(
hour, minute, second, microsecond)
_check_tzinfo_arg(tzinfo)
- self = object.__new__(cls)
+ self = timeinterop.__new__(cls)
self._hour = hour
self._minute = minute
self._second = second
@@ -1408,7 +1411,7 @@
if isinstance(year, bytes) and len(year) == 10 and \
1 <= ord(year[2]) <= 12:
# Pickle support
- self = object.__new__(cls)
+ self = dateinterop.__new__(cls)
self.__setstate(year, month)
self._hashcode = -1
return self
@@ -1416,7 +1419,7 @@
hour, minute, second, microsecond = _check_time_fields(
hour, minute, second, microsecond)
_check_tzinfo_arg(tzinfo)
- self = object.__new__(cls)
+ self = dateinterop.__new__(cls)
self._year = year
self._month = month
self._day = day
@@ -1461,7 +1464,7 @@
A timezone info object may be passed in as well.
"""
_check_tzinfo_arg(tz)
- converter = _time.localtime if tz is None else _time.gmtime
+ converter = _timemodule.localtime if tz is None else _timemodule.gmtime
self = cls._from_timestamp(converter, timestamp, tz)
if tz is not None:
self = tz.fromutc(self)
@@ -1470,7 +1473,7 @@
@classmethod
def utcfromtimestamp(cls, t):
"Construct a UTC datetime from a POSIX timestamp (like time.time())."
- return cls._from_timestamp(_time.gmtime, t, None)
+ return cls._from_timestamp(_timemodule.gmtime, t, None)
@classmethod
def _from_timestamp(cls, converter, timestamp, tzinfo):
@@ -1493,13 +1496,13 @@
@classmethod
def now(cls, tz=None):
"Construct a datetime from time.time() and optional time zone info."
- t = _time.time()
+ t = _timemodule.time()
return cls.fromtimestamp(t, tz)
@classmethod
def utcnow(cls):
"Construct a UTC datetime from time.time()."
- t = _time.time()
+ t = _timemodule.time()
return cls.utcfromtimestamp(t)
@classmethod
diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py
--- a/pypy/module/__pypy__/__init__.py
+++ b/pypy/module/__pypy__/__init__.py
@@ -58,6 +58,14 @@
}
+class PyPyDateTime(MixedModule):
+ appleveldefs = {}
+ interpleveldefs = {
+ 'dateinterop': 'interp_pypydatetime.W_DateTime_Date',
+ 'timeinterop' : 'interp_pypydatetime.W_DateTime_Time',
+ 'deltainterop' : 'interp_pypydatetime.W_DateTime_Delta',
+ }
+
class Module(MixedModule):
""" PyPy specific "magic" functions. A lot of them are experimental and
subject to change, many are internal. """
@@ -108,6 +116,7 @@
"thread": ThreadModule,
"intop": IntOpModule,
"os": OsModule,
+ '_pypydatetime': PyPyDateTime,
}
def setup_after_space_initialization(self):
diff --git a/pypy/module/__pypy__/interp_pypydatetime.py b/pypy/module/__pypy__/interp_pypydatetime.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/__pypy__/interp_pypydatetime.py
@@ -0,0 +1,24 @@
+from pypy.interpreter.baseobjspace import W_Root
+from pypy.interpreter.typedef import TypeDef
+from pypy.interpreter.gateway import interp2app
+from rpython.tool.sourcetools import func_with_new_name
+
+def create_class(name):
+ class W_Class(W_Root):
+ 'builtin base clasee for datetime.%s to allow interop with cpyext' % name
+ def descr_new__(space, w_type):
+ return space.allocate_instance(W_Class, w_type)
+
+ W_Class.typedef = TypeDef(name,
+ __new__ = interp2app(func_with_new_name(
+ W_Class.descr_new__.im_func,
+ '%s_new' % (name,))),
+ )
+ W_Class.typedef.acceptable_as_base_class = True
+ return W_Class
+
+W_DateTime_Time = create_class('pypydatetime_time')
+W_DateTime_Date = create_class('pypydatetime_date')
+W_DateTime_Delta = create_class('pypydatetime_delta')
+
+
diff --git a/pypy/module/cpyext/cdatetime.py b/pypy/module/cpyext/cdatetime.py
--- a/pypy/module/cpyext/cdatetime.py
+++ b/pypy/module/cpyext/cdatetime.py
@@ -1,11 +1,14 @@
from rpython.rtyper.lltypesystem import rffi, lltype
from rpython.rtyper.annlowlevel import llhelper
-from pypy.module.cpyext.pyobject import PyObject, make_ref, make_typedescr
+from pypy.module.cpyext.pyobject import (PyObject, make_ref, make_typedescr,
+ decref)
from pypy.module.cpyext.api import (cpython_api, CANNOT_FAIL, cpython_struct,
PyObjectFields, cts, parse_dir, bootstrap_function, slot_function)
from pypy.module.cpyext.import_ import PyImport_Import
from pypy.module.cpyext.typeobject import PyTypeObjectPtr
from pypy.interpreter.error import OperationError
+from pypy.module.__pypy__.interp_pypydatetime import (W_DateTime_Date,
+ W_DateTime_Time, W_DateTime_Delta)
from rpython.tool.sourcetools import func_renamer
cts.parse_header(parse_dir / 'cpyext_datetime.h')
@@ -56,7 +59,7 @@
return datetimeAPI
PyDateTime_Time = cts.gettype('PyDateTime_Time*')
-PyDateTime_DateTime = cts.gettype('PyDateTime_DateTime*')
+PyDateTime_Date = cts.gettype('PyDateTime_Date*')
PyDateTime_Delta = cts.gettype('PyDateTime_Delta*')
# Check functions
@@ -69,6 +72,8 @@
return space.is_true(
space.appexec([w_obj], """(obj):
from datetime import %s as datatype
+ if not isinstance(obj, datatype):
+ print datatype
return isinstance(obj, datatype)
""" % (type_name,)))
except OperationError:
@@ -98,54 +103,39 @@
@bootstrap_function
def init_datetime(space):
- w_datetime = PyImport_Import(space, space.newtext("datetime"))
-
- w_datetimetype = space.getattr(w_datetime, space.newtext("datetime"))
- w_timetype = space.getattr(w_datetime, space.newtext("time"))
- w_timedeltatype = space.getattr(w_datetime, space.newtext("timedelta"))
-
- # XXX doesn't work, the w_datetimetype, w_timetype, w_timedeltatype all
- # share the object layout.typedef so the typedescr specialization fails
- return
# no realize functions since there are no getters
- make_typedescr(w_datetimetype.layout.typedef,
- basestruct=PyDateTime_DateTime.TO,
- attach=type_attach,
- dealloc=type_dealloc,
- )
-
- make_typedescr(w_timetype.layout.typedef,
+ make_typedescr(W_DateTime_Time.typedef,
basestruct=PyDateTime_Time.TO,
attach=type_attach,
dealloc=type_dealloc,
)
- make_typedescr(w_timedeltatype.layout.typedef,
+ make_typedescr(W_DateTime_Delta.typedef,
basestruct=PyDateTime_Delta.TO,
attach=timedeltatype_attach,
)
def type_attach(space, py_obj, w_obj, w_userdata=None):
- "Fills a newly allocated py_obj from the w_obj"
- import pdb;pdb.set_trace()
+ '''Fills a newly allocated py_obj from the w_obj
+ Can be called with a datetime, or a time
+ '''
py_datetime = rffi.cast(PyDateTime_Time, py_obj)
- w_tzinfo = space.getattr(w_obj, space.wrap('tzinfo'))
+ w_tzinfo = space.getattr(w_obj, space.newtext('tzinfo'))
if space.is_none(w_tzinfo):
py_datetime.c_hastzinfo = 0
py_datetime.c_tzinfo = lltype.nullptr(PyObject.TO)
else:
py_datetime.c_hastzinfo = 1
- py_datetime.c_tzinfo = make_ref(w_tzinfo)
+ py_datetime.c_tzinfo = make_ref(space, w_tzinfo)
@slot_function([PyObject], lltype.Void)
def type_dealloc(space, py_obj):
- import pdb;pdb.set_trace()
py_datetime = rffi.cast(PyDateTime_Time, py_obj)
- if (py_datetime.hastzinfo):
+ if (py_datetime.c_hastzinfo != 0):
decref(space, py_datetime.c_tzinfo)
from pypy.module.cpyext.object import _dealloc
_dealloc(space, py_obj)
-
+
def timedeltatype_attach(space, py_obj, w_obj, w_userdata=None):
"Fills a newly allocated py_obj from the w_obj"
py_delta = rffi.cast(PyDateTime_Delta, py_obj)
diff --git a/pypy/module/cpyext/parse/cpyext_datetime.h b/pypy/module/cpyext/parse/cpyext_datetime.h
--- a/pypy/module/cpyext/parse/cpyext_datetime.h
+++ b/pypy/module/cpyext/parse/cpyext_datetime.h
@@ -18,9 +18,9 @@
typedef struct
{
PyObject_HEAD
- int days; /* -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS */
- int seconds; /* 0 <= seconds < 24*3600 is invariant */
- int microseconds; /* 0 <= microseconds < 1000000 is invariant */
+ long days; /* -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS */
+ long seconds; /* 0 <= seconds < 24*3600 is invariant */
+ long microseconds; /* 0 <= microseconds < 1000000 is invariant */
} PyDateTime_Delta;
/* The datetime and time types have an optional tzinfo member,
@@ -29,14 +29,14 @@
typedef struct
{
PyObject_HEAD
- char hastzinfo;
+ long hastzinfo;
PyObject *tzinfo;
} PyDateTime_Time;
typedef struct
{
PyObject_HEAD
- char hastzinfo;
+ long hastzinfo;
PyObject *tzinfo;
} PyDateTime_DateTime;
More information about the pypy-commit
mailing list