[Python-checkins] python/nondist/sandbox/datetime obj_timetz.c,NONE,1.1 datetime.c,1.52,1.53 datetime.h,1.12,1.13

tim_one@users.sourceforge.net tim_one@users.sourceforge.net
Mon, 09 Dec 2002 18:04:29 -0800


Update of /cvsroot/python/python/nondist/sandbox/datetime
In directory sc8-pr-cvs1:/tmp/cvs-serv5008

Modified Files:
	datetime.c datetime.h 
Added Files:
	obj_timetz.c 
Log Message:
Added wholly non-functional code for the timetz -- this is just a copy,
paste, and mindless edit of the time code.


--- NEW FILE: obj_timetz.c ---
/*
 * PyDateTime_TimeTZ implementation.
 */

/* Accessor properties. */

static PyObject *
timetz_hour(PyDateTime_TimeTZ *self, void *unused)
{
	return PyInt_FromLong(TIME_GET_HOUR(self));
}

static PyObject *
timetz_minute(PyDateTime_TimeTZ *self, void *unused)
{
	return PyInt_FromLong(TIME_GET_MINUTE(self));
}

static PyObject *
timetz_second(PyDateTime_TimeTZ *self, void *unused)
{
	return PyInt_FromLong(TIME_GET_SECOND(self));
}

static PyObject *
timetz_microsecond(PyDateTime_TimeTZ *self, void *unused)
{
	return PyInt_FromLong(TIME_GET_MICROSECOND(self));
}

static PyGetSetDef timetz_getset[] = {
	{"hour",        (getter)timetz_hour},
	{"minute",      (getter)timetz_minute},
	{"second",      (getter)timetz_second},
	{"microsecond", (getter)timetz_microsecond},
	{NULL}
};

/* Constructors. */

static PyObject *
timetz_new(PyTypeObject *type, PyObject *args, PyObject *kw)
{
	PyObject *self = NULL;
	long hour = 0;
	long minute = 0;
	long second = 0;
	long usecond = 0;

	static char *keywords[] = {
		"hour", "minute", "second", "microsecond", NULL
	};

	if (PyArg_ParseTupleAndKeywords(args, kw, "|llll", keywords,
					&hour, &minute, &second, &usecond)) {
		if (hour < 0 || hour > 23) {
			PyErr_SetString(PyExc_ValueError,
					"hour must be in 0..23");
			return NULL;
		}
		if (minute < 0 || minute > 59) {
			PyErr_SetString(PyExc_ValueError,
					"minute must be in 0..59");
			return NULL;
		}
		if (second < 0 || second > 59) {
			PyErr_SetString(PyExc_ValueError,
					"second must be in 0..59");
			return NULL;
		}
		if (usecond < 0 || usecond > 999999) {
			PyErr_SetString(PyExc_ValueError,
					"microsecond must be in 0..999999");
			return NULL;
		}
		self = new_time(hour, minute, second, usecond);
	}
	return self;
}

/* Various ways to turn a time into a string. */

static PyObject *
timetz_repr(PyDateTime_TimeTZ *self)
{
	char buffer[100];
	char *typename = self->ob_type->tp_name;
	int h = TIME_GET_HOUR(self);
	int m = TIME_GET_MINUTE(self);
	int s = TIME_GET_SECOND(self);
	int us = TIME_GET_MICROSECOND(self);

	if (us)
		PyOS_snprintf(buffer, sizeof(buffer),
			      "%s(%d, %d, %d, %d)", typename, h, m, s, us);
	else if (s)
		PyOS_snprintf(buffer, sizeof(buffer),
			      "%s(%d, %d, %d)", typename, h, m, s);
	else
		PyOS_snprintf(buffer, sizeof(buffer),
			      "%s(%d, %d)", typename, h, m);
	return PyString_FromString(buffer);
}

static PyObject *
timetz_str(PyDateTime_TimeTZ *self)
{
	return PyObject_CallMethod((PyObject *)self, "isoformat", "()");
}

static PyObject *
timetz_isoformat(PyDateTime_TimeTZ *self)
{
	char buffer[100];
	/* Reuse the time format code from the datetime type. */
	PyDateTime_DateTime datetime;
	PyDateTime_DateTime *pdatetime = &datetime;

	/* Copy over just the time bytes. */
	memcpy(pdatetime->data + _PyDateTime_DATE_DATASIZE,
	       self->data,
	       _PyDateTime_TIME_DATASIZE);

	isoformat_time(pdatetime, buffer, sizeof(buffer));
	return PyString_FromString(buffer);
}

static PyObject *
timetz_strftime(PyDateTime_TimeTZ *self, PyObject *format)
{
	PyObject *result;
	PyObject *tuple = Py_BuildValue("iiiiiiiii",
				        0, 0, 0, /* year, month, day */
				        TIME_GET_HOUR(self),
				        TIME_GET_MINUTE(self),
				        TIME_GET_SECOND(self),
				        0, 0, -1); /* weekday, daynum, dst */
	if (tuple == NULL)
		return NULL;
	assert(PyTuple_Size(tuple) == 9);
	result = format_strftime(format, tuple);
	Py_DECREF(tuple);
	return result;
}

/* Miscellaneous methods. */

/* This is more natural as a tp_compare, but doesn't work then:  for whatever
 * reason, Python's try_3way_compare ignores tp_compare unless
 * PyInstance_Check returns true, but these aren't old-style classes.
 */
static PyObject *
timetz_richcompare(PyDateTime_TimeTZ *self, PyObject *other, int op)
{
	long diff;

	if (!PyType_IsSubtype(other->ob_type, &PyDateTime_TimeType)) {
		PyErr_Format(PyExc_TypeError,
			     "can't compare time to %s instance",
			     other->ob_type->tp_name);
		return NULL;
	}
	diff = memcmp(self->data, ((PyDateTime_TimeTZ *)other)->data,
		      _PyDateTime_TIME_DATASIZE);
	return diff_to_bool(diff, op);
}

static PyObject *timetz_getstate(PyDateTime_TimeTZ *self);

static long
timetz_hash(PyDateTime_TimeTZ *self)
{
	if (self->hashcode == -1) {
		PyObject *temp = timetz_getstate(self);
		if (temp != NULL) {
			self->hashcode = PyObject_Hash(temp);
			Py_DECREF(temp);
		}
	}
	return self->hashcode;
}

static int
timetz_nonzero(PyDateTime_TimeTZ *self)
{
	return TIME_GET_HOUR(self) ||
	       TIME_GET_MINUTE(self) ||
	       TIME_GET_SECOND(self) ||
	       TIME_GET_MICROSECOND(self);
}

/* Pickle support.  Quite a maze! */

static PyObject *
timetz_getstate(PyDateTime_TimeTZ *self)
{
	return PyString_FromStringAndSize(self->data,
					  _PyDateTime_TIME_DATASIZE);
}

static PyObject *
timetz_setstate(PyDateTime_TimeTZ *self, PyObject *state)
{
	const int len = PyString_Size(state);
	unsigned char *pdata = (unsigned char*)PyString_AsString(state);

	if (! PyString_Check(state) ||
	    len != _PyDateTime_TIME_DATASIZE) {
		PyErr_SetString(PyExc_TypeError,
				"bad argument to time.__setstate__");
		return NULL;
	}
	memcpy(self->data, pdata, _PyDateTime_TIME_DATASIZE);
	self->hashcode = -1;

	Py_INCREF(Py_None);
	return Py_None;
}

/* XXX This seems a ridiculously inefficient way to pickle a short string. */
static PyObject *
timetz_pickler(PyObject *module, PyDateTime_TimeTZ *time)
{
	PyObject *state;
	PyObject *result = NULL;

	if (time->ob_type != &PyDateTime_TimeTZType) {
		PyErr_Format(PyExc_TypeError,
			     "bad type passed to time pickler: %s",
			     time->ob_type->tp_name);
		return NULL;
	}
	state = timetz_getstate(time);
	if (state) {
		result = Py_BuildValue("O(O)",
				       time_unpickler_object,
				       state);
		Py_DECREF(state);
	}
	return result;
}

static PyObject *
timetz_unpickler(PyObject *module, PyObject *arg)
{
	PyDateTime_TimeTZ *self;

	if (! PyString_CheckExact(arg)) {
		PyErr_Format(PyExc_TypeError,
			     "bad type passed to time unpickler: %s",
			     arg->ob_type->tp_name);
		return NULL;
	}
	self = PyObject_New(PyDateTime_TimeTZ, &PyDateTime_TimeTZType);
	if (self != NULL) {
		PyObject *res = timetz_setstate(self, arg);
		Py_XDECREF(res);
	}
	return (PyObject *)self;
}

static PyMethodDef timetz_methods[] = {
	{"isoformat",   (PyCFunction)timetz_isoformat,	METH_KEYWORDS,
	 PyDoc_STR("Return string in ISO 8601 format, HH:MM:SS[.mmmmmm].")},

	{"strftime",   	(PyCFunction)timetz_strftime,	METH_O,
	 PyDoc_STR("format -> strftime() style string.")},

	{"__setstate__", (PyCFunction)timetz_setstate,	METH_O,
	 PyDoc_STR("__setstate__(state)")},

	{"__getstate__", (PyCFunction)timetz_getstate,	METH_NOARGS,
	 PyDoc_STR("__getstate__() -> state")},
	{NULL,	NULL}
};

static char timetz_doc[] =
PyDoc_STR("Time type.");

static PyNumberMethods timetz_as_number = {
	0,					/* nb_add */
	0,					/* nb_subtract */
	0,					/* nb_multiply */
	0,					/* nb_divide */
	0,					/* nb_remainder */
	0,					/* nb_divmod */
	0,					/* nb_power */
	0,					/* nb_negative */
	0,					/* nb_positive */
	0,					/* nb_absolute */
	(inquiry)time_nonzero,			/* nb_nonzero */
};

statichere PyTypeObject PyDateTime_TimeTZType = {
	PyObject_HEAD_INIT(NULL)
	0,					/* ob_size */
	/* XXX When this module is renamed to datetime, change tp_name. */
	"_datetime.time",			/* tp_name */
	sizeof(PyDateTime_TimeTZ),		/* tp_basicsize */
	0,					/* tp_itemsize */
	(destructor)PyObject_Del,		/* tp_dealloc */
	0,					/* tp_print */
	0,					/* tp_getattr */
	0,					/* tp_setattr */
	0,					/* tp_compare */
	(reprfunc)timetz_repr,			/* tp_repr */
	&timetz_as_number,			/* tp_as_number */
	0,					/* tp_as_sequence */
	0,					/* tp_as_mapping */
	(hashfunc)timetz_hash,			/* tp_hash */
	0,              			/* tp_call */
	(reprfunc)timetz_str,			/* tp_str */
	PyObject_GenericGetAttr,		/* tp_getattro */
	0,					/* tp_setattro */
	0,					/* tp_as_buffer */
	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
        Py_TPFLAGS_BASETYPE,			/* tp_flags */
	time_doc,				/* tp_doc */
	0,					/* tp_traverse */
	0,					/* tp_clear */
	(richcmpfunc)time_richcompare,		/* tp_richcompare */
	0,					/* tp_weaklistoffset */
	0,					/* tp_iter */
	0,					/* tp_iternext */
	time_methods,				/* tp_methods */
	0,					/* tp_members */
	time_getset,				/* tp_getset */
	&PyDateTime_TimeType,			/* tp_base */
	0,					/* tp_dict */
	0,					/* tp_descr_get */
	0,					/* tp_descr_set */
	0,					/* tp_dictoffset */
	0,					/* tp_init */
	0,					/* tp_alloc */
	timetz_new,				/* tp_new */
	_PyObject_Del,				/* tp_free */
};

Index: datetime.c
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.c,v
retrieving revision 1.52
retrieving revision 1.53
diff -C2 -d -r1.52 -r1.53
*** datetime.c	9 Dec 2002 21:37:37 -0000	1.52
--- datetime.c	10 Dec 2002 02:04:26 -0000	1.53
***************
*** 72,75 ****
--- 72,76 ----
  static PyTypeObject PyDateTime_DeltaType;
  static PyTypeObject PyDateTime_TimeType;
+ static PyTypeObject PyDateTime_TimeTZType;
  
  /*
***************
*** 632,635 ****
--- 633,637 ----
  static PyObject *datetime_unpickler_object = NULL;
  static PyObject *time_unpickler_object = NULL;
+ static PyObject *timetz_unpickler_object = NULL;
  
  /* For obscure reasons, we need to use tp_richcompare instead of tp_compare.
***************
*** 663,666 ****
--- 665,669 ----
  #include "obj_datetime.c"
  #include "obj_time.c"
+ #include "obj_timetz.c"
  
  
***************
*** 675,678 ****
--- 678,683 ----
  	{"_time_pickler",	(PyCFunction)time_pickler,	METH_O, NULL},
  	{"_time_unpickler",	(PyCFunction)time_unpickler,	METH_O, NULL},
+ 	{"_timetz_pickler",	(PyCFunction)timetz_pickler,	METH_O, NULL},
+ 	{"_timetz_unpickler",	(PyCFunction)timetz_unpickler,	METH_O, NULL},
  	{NULL, NULL}
  };
***************
*** 699,702 ****
--- 704,709 ----
  	if (PyType_Ready(&PyDateTime_TimeType) < 0)
  		return;
+ 	if (PyType_Ready(&PyDateTime_TimeTZType) < 0)
+ 		return;
  
  	/* timedelta values */
***************
*** 796,799 ****
--- 803,809 ----
  	PyModule_AddObject(m, "time", (PyObject *) &PyDateTime_TimeType);
  
+ 	Py_INCREF(&PyDateTime_TimeTZType);
+ 	PyModule_AddObject(m, "timetz", (PyObject *) &PyDateTime_TimeTZType);
+ 
  
  	/* A 4-year cycle has an extra leap day over what we'd get from
***************
*** 875,878 ****
--- 885,900 ----
  		Py_DECREF(pickler);
  
+ 		pickler = PyObject_GetAttrString(m, "_timetz_pickler");
+ 		assert(pickler);
+ 		timetz_unpickler_object = PyObject_GetAttrString(m,
+ 						"_timetz_unpickler");
+ 		assert(time_unpickler_object);
+ 	    	temp = PyObject_CallMethod(copyreg, "pickle", "OOO",
+ 	    				   &PyDateTime_TimeTZType,
+ 	    				   pickler,
+ 		                           timetz_unpickler_object);
+ 		assert(temp);
+ 		Py_DECREF(temp);
+ 		Py_DECREF(pickler);
  		Py_DECREF(copyreg);
  	}

Index: datetime.h
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -C2 -d -r1.12 -r1.13
*** datetime.h	7 Dec 2002 18:34:39 -0000	1.12
--- datetime.h	10 Dec 2002 02:04:26 -0000	1.13
***************
*** 53,56 ****
--- 53,64 ----
  {
  	PyObject_HEAD
+ 	long hashcode;
+ 	unsigned char data[_PyDateTime_TIME_DATASIZE];
+ 	PyObject *tzinfo;
+ } PyDateTime_TimeTZ;
+ 
+ typedef struct
+ {
+ 	PyObject_HEAD
  	long hashcode;		/* -1 when unknown */
  	long days;		/* -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS */
***************
*** 74,78 ****
            ((PyDateTime_DateTime*)o)->data[9])
  
! /* Apply for time instances. */
  #define PyDateTime_TIME_GET_HOUR(o)        (((PyDateTime_Time*)o)->data[0])
  #define PyDateTime_TIME_GET_MINUTE(o)      (((PyDateTime_Time*)o)->data[1])
--- 82,86 ----
            ((PyDateTime_DateTime*)o)->data[9])
  
! /* Apply for time and timetz instances. */
  #define PyDateTime_TIME_GET_HOUR(o)        (((PyDateTime_Time*)o)->data[0])
  #define PyDateTime_TIME_GET_MINUTE(o)      (((PyDateTime_Time*)o)->data[1])