[Python-checkins] CVS: python/dist/src/Modules posixmodule.c,2.202,2.203 timemodule.c,2.114,2.115

Guido van Rossum gvanrossum@users.sourceforge.net
Thu, 18 Oct 2001 13:34:28 -0700


Update of /cvsroot/python/python/dist/src/Modules
In directory usw-pr-cvs1:/tmp/cvs-serv7266/Modules

Modified Files:
	posixmodule.c timemodule.c 
Log Message:
SF patch #462296: Add attributes to os.stat results; by Nick Mathewson.

This is a big one, touching lots of files.  Some of the platforms
aren't tested yet.  Briefly, this changes the return value of the
os/posix functions stat(), fstat(), statvfs(), fstatvfs(), and the
time functions localtime(), gmtime(), and strptime() from tuples into
pseudo-sequences.  When accessed as a sequence, they behave exactly as
before.  But they also have attributes like st_mtime or tm_year.  The
stat return value, moreover, has a few platform-specific attributes
that are not available through the sequence interface (because
everybody expects the sequence to have a fixed length, these couldn't
be added there).  If your platform's struct stat doesn't define
st_blksize, st_blocks or st_rdev, they won't be accessible from Python
either.

(Still missing is a documentation update.)



Index: posixmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/posixmodule.c,v
retrieving revision 2.202
retrieving revision 2.203
diff -C2 -d -r2.202 -r2.203
*** posixmodule.c	2001/10/18 19:44:10	2.202
--- posixmodule.c	2001/10/18 20:34:25	2.203
***************
*** 18,21 ****
--- 18,22 ----
  
  #include "Python.h"
+ #include "structseq.h"
  
  #if defined(PYOS_OS2)
***************
*** 517,520 ****
--- 518,612 ----
  }
  
+ static char stat_result__doc__[] = 
+ "stat_result: Result from stat or lstat.\n\n\
+ This object may be accessed either as a tuple of\n\
+   (mode,ino,dev,nlink,uid,gid,size,atime,mtime,ctime)\n\
+ or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
+ \n\
+ Posix/windows: If your platform supports st_blksize, st_blocks, or st_rdev,
+ they are available as attributes only.\n\
+ \n\
+ See os.stat for more information.\n";
+ 
+ static PyStructSequence_Field stat_result_fields[] = {
+ 	{"st_mode",    "protection bits"},
+ 	{"st_ino",     "inode"},
+ 	{"st_dev",     "device"},
+ 	{"st_nlink",   "number of hard links"},
+ 	{"st_uid",     "user ID of owner"},
+ 	{"st_gid",     "group ID of owner"},
+ 	{"st_size",    "total size, in bytes"},
+ 	{"st_atime",   "time of last access"},
+ 	{"st_mtime",   "time of last modification"},
+ 	{"st_ctime",   "time of last change"},
+ #ifdef HAVE_ST_BLKSIZE
+ 	{"st_blksize", "blocksize for filesystem I/O"},
+ #endif
+ #ifdef HAVE_ST_BLOCKS
+ 	{"st_blocks",  "number of blocks allocated"},
+ #endif
+ #ifdef HAVE_ST_RDEV
+ 	{"st_rdev",    "device type (if inode device)"},
+ #endif
+ 	{0}
+ };
+ 
+ #ifdef HAVE_ST_BLKSIZE
+ #define ST_BLKSIZE_IDX 10
+ #else
+ #define ST_BLKSIZE_IDX 9
+ #endif
+ 
+ #ifdef HAVE_ST_BLOCKS
+ #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
+ #else
+ #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
+ #endif
+ 
+ #ifdef HAVE_ST_RDEV
+ #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
+ #else
+ #define ST_RDEV_IDX ST_BLOCKS_IDX
+ #endif
+ 
+ static PyStructSequence_Desc stat_result_desc = {
+ 	"stat_result", /* name */
+ 	stat_result__doc__, /* doc */
+ 	stat_result_fields,
+ 	10
+ };
+ 
+ static char statvfs_result__doc__[] = 
+ "statvfs_result: Result from statvfs or fstatvfs.\n\n\
+ This object may be accessed either as a tuple of\n\
+   (bsize,frsize,blocks,bfree,bavail,files,ffree,favail,flag,namemax),
+ or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.
+ \n\
+ See os.statvfs for more information.\n";
+ 
+ static PyStructSequence_Field statvfs_result_fields[] = {
+         {"f_bsize",  },
+         {"f_frsize", },
+         {"f_blocks", },
+         {"f_bfree",  },
+         {"f_bavail", },
+         {"f_files",  },
+         {"f_ffree",  },
+         {"f_favail", },
+         {"f_flag",   },
+         {"f_namemax",},
+         {0}
+ };
+ 
+ static PyStructSequence_Desc statvfs_result_desc = {
+ 	"statvfs_result", /* name */
+ 	statvfs_result__doc__, /* doc */
+ 	statvfs_result_fields,
+ 	10
+ };
+ 
+ static PyTypeObject StatResultType;
+ static PyTypeObject StatVFSResultType;
+ 
  /* pack a system stat C structure into the Python stat tuple 
     (used by posix_stat() and posix_fstat()) */
***************
*** 522,558 ****
  _pystat_fromstructstat(STRUCT_STAT st)
  {
! 	PyObject *v = PyTuple_New(10);
  	if (v == NULL)
  		return NULL;
  
! 	PyTuple_SetItem(v, 0, PyInt_FromLong((long)st.st_mode));
  #ifdef HAVE_LARGEFILE_SUPPORT
! 	PyTuple_SetItem(v, 1, PyLong_FromLongLong((LONG_LONG)st.st_ino));
  #else
! 	PyTuple_SetItem(v, 1, PyInt_FromLong((long)st.st_ino));
  #endif
  #if defined(HAVE_LONG_LONG) && !defined(MS_WINDOWS)
! 	PyTuple_SetItem(v, 2, PyLong_FromLongLong((LONG_LONG)st.st_dev));
  #else
! 	PyTuple_SetItem(v, 2, PyInt_FromLong((long)st.st_dev));
  #endif
! 	PyTuple_SetItem(v, 3, PyInt_FromLong((long)st.st_nlink));
! 	PyTuple_SetItem(v, 4, PyInt_FromLong((long)st.st_uid));
! 	PyTuple_SetItem(v, 5, PyInt_FromLong((long)st.st_gid));
  #ifdef HAVE_LARGEFILE_SUPPORT
! 	PyTuple_SetItem(v, 6, PyLong_FromLongLong((LONG_LONG)st.st_size));
  #else
! 	PyTuple_SetItem(v, 6, PyInt_FromLong(st.st_size));
  #endif
  #if SIZEOF_TIME_T > SIZEOF_LONG
! 	PyTuple_SetItem(v, 7, PyLong_FromLongLong((LONG_LONG)st.st_atime));
! 	PyTuple_SetItem(v, 8, PyLong_FromLongLong((LONG_LONG)st.st_mtime));
! 	PyTuple_SetItem(v, 9, PyLong_FromLongLong((LONG_LONG)st.st_ctime));
  #else
! 	PyTuple_SetItem(v, 7, PyInt_FromLong((long)st.st_atime));
! 	PyTuple_SetItem(v, 8, PyInt_FromLong((long)st.st_mtime));
! 	PyTuple_SetItem(v, 9, PyInt_FromLong((long)st.st_ctime));
  #endif
  
  	if (PyErr_Occurred()) {
  		Py_DECREF(v);
--- 614,669 ----
  _pystat_fromstructstat(STRUCT_STAT st)
  {
! 	PyObject *v = PyStructSequence_New(&StatResultType);
  	if (v == NULL)
  		return NULL;
  
!         PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long)st.st_mode));
  #ifdef HAVE_LARGEFILE_SUPPORT
!         PyStructSequence_SET_ITEM(v, 1, 
! 				  PyLong_FromLongLong((LONG_LONG)st.st_ino));
  #else
!         PyStructSequence_SET_ITEM(v, 1, PyInt_FromLong((long)st.st_ino));
  #endif
  #if defined(HAVE_LONG_LONG) && !defined(MS_WINDOWS)
!         PyStructSequence_SET_ITEM(v, 2, 
! 				  PyLong_FromLongLong((LONG_LONG)st.st_dev));
  #else
!         PyStructSequence_SET_ITEM(v, 2, PyInt_FromLong((long)st.st_dev));
  #endif
!         PyStructSequence_SET_ITEM(v, 3, PyInt_FromLong((long)st.st_nlink));
!         PyStructSequence_SET_ITEM(v, 4, PyInt_FromLong((long)st.st_uid));
!         PyStructSequence_SET_ITEM(v, 5, PyInt_FromLong((long)st.st_gid));
  #ifdef HAVE_LARGEFILE_SUPPORT
!         PyStructSequence_SET_ITEM(v, 6, 
! 				  PyLong_FromLongLong((LONG_LONG)st.st_size));
  #else
!         PyStructSequence_SET_ITEM(v, 6, PyInt_FromLong(st.st_size));
  #endif
  #if SIZEOF_TIME_T > SIZEOF_LONG
!         PyStructSequence_SET_ITEM(v, 7, 
! 				  PyLong_FromLongLong((LONG_LONG)st.st_atime));
!         PyStructSequence_SET_ITEM(v, 8, 
! 				  PyLong_FromLongLong((LONG_LONG)st.st_mtime));
!         PyStructSequence_SET_ITEM(v, 9, 
! 				  PyLong_FromLongLong((LONG_LONG)st.st_ctime));
  #else
! 	PyStructSequence_SET_ITEM(v, 7, PyInt_FromLong((long)st.st_atime));
!         PyStructSequence_SET_ITEM(v, 8, PyInt_FromLong((long)st.st_mtime));
!         PyStructSequence_SET_ITEM(v, 9, PyInt_FromLong((long)st.st_ctime));
  #endif
  
+ #ifdef HAVE_ST_BLKSIZE
+ 	PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX, 
+ 			 PyInt_FromLong((long)st.st_blksize));
+ #endif
+ #ifdef HAVE_ST_BLOCKS
+ 	PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX, 
+ 			 PyInt_FromLong((long)st.st_blocks));
+ #endif
+ #ifdef HAVE_ST_RDEV
+ 	PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
+ 			 PyInt_FromLong((long)st.st_rdev));
+ #endif
+ 
  	if (PyErr_Occurred()) {
  		Py_DECREF(v);
***************
*** 563,567 ****
  }
  
- 
  static PyObject *
  posix_do_stat(PyObject *self, PyObject *args, char *format,
--- 674,677 ----
***************
*** 4174,4177 ****
--- 4284,4326 ----
  #include <sys/statvfs.h>
  
+ static PyObject*
+ _pystatvfs_fromstructstatvfs(struct statvfs st) {
+         PyObject *v = PyStructSequence_New(&StatVFSResultType);
+ 	if (v == NULL)
+ 		return NULL;
+ 
+ #if !defined(HAVE_LARGEFILE_SUPPORT)
+         PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long) st.f_bsize));
+         PyStructSequence_SET_ITEM(v, 1, PyInt_FromLong((long) st.f_frsize));
+         PyStructSequence_SET_ITEM(v, 2, PyInt_FromLong((long) st.f_blocks));
+         PyStructSequence_SET_ITEM(v, 3, PyInt_FromLong((long) st.f_bfree));
+         PyStructSequence_SET_ITEM(v, 4, PyInt_FromLong((long) st.f_bavail));
+         PyStructSequence_SET_ITEM(v, 5, PyInt_FromLong((long) st.f_files));
+         PyStructSequence_SET_ITEM(v, 6, PyInt_FromLong((long) st.f_ffree));
+         PyStructSequence_SET_ITEM(v, 7, PyInt_FromLong((long) st.f_favail));
+         PyStructSequence_SET_ITEM(v, 8, PyInt_FromLong((long) st.f_flag));
+         PyStructSequence_SET_ITEM(v, 9, PyInt_FromLong((long) st.f_namemax));
+ #else
+         PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long) st.f_bsize));
+         PyStructSequence_SET_ITEM(v, 1, PyInt_FromLong((long) st.f_frsize));
+         PyStructSequence_SET_ITEM(v, 2, 
+ 			       PyLong_FromLongLong((LONG_LONG) st.f_blocks));
+         PyStructSequence_SET_ITEM(v, 3, 
+ 			       PyLong_FromLongLong((LONG_LONG) st.f_bfree));
+         PyStructSequence_SET_ITEM(v, 4,
+ 			       PyLong_FromLongLong((LONG_LONG) st.f_bavail));
+         PyStructSequence_SET_ITEM(v, 5, 
+ 			       PyLong_FromLongLong((LONG_LONG) st.f_files));
+         PyStructSequence_SET_ITEM(v, 6, 
+ 			       PyLong_FromLongLong((LONG_LONG) st.f_ffree));
+         PyStructSequence_SET_ITEM(v, 7, 
+ 			       PyLong_FromLongLong((LONG_LONG) st.f_favail));
+         PyStructSequence_SET_ITEM(v, 8, PyInt_FromLong((long) st.f_flag));
+         PyStructSequence_SET_ITEM(v, 9, PyInt_FromLong((long) st.f_namemax));
+ #endif
+ 
+         return v;
+ }
+ 
  static char posix_fstatvfs__doc__[] =
  "fstatvfs(fd) -> \n\
***************
*** 4184,4187 ****
--- 4333,4337 ----
  	int fd, res;
  	struct statvfs st;
+ 
  	if (!PyArg_ParseTuple(args, "i:fstatvfs", &fd))
  		return NULL;
***************
*** 4191,4219 ****
  	if (res != 0)
  		return posix_error();
! #if !defined(HAVE_LARGEFILE_SUPPORT)
! 	return Py_BuildValue("(llllllllll)",
! 		    (long) st.f_bsize,
! 		    (long) st.f_frsize,
! 		    (long) st.f_blocks,
! 		    (long) st.f_bfree,
! 		    (long) st.f_bavail,
! 		    (long) st.f_files,
! 		    (long) st.f_ffree,
! 		    (long) st.f_favail,
! 		    (long) st.f_flag,
! 		    (long) st.f_namemax);
! #else
! 	return Py_BuildValue("(llLLLLLLll)",
! 		    (long) st.f_bsize,
! 		    (long) st.f_frsize,
! 		    (LONG_LONG) st.f_blocks,
! 		    (LONG_LONG) st.f_bfree,
! 		    (LONG_LONG) st.f_bavail,
! 		    (LONG_LONG) st.f_files,
! 		    (LONG_LONG) st.f_ffree,
! 		    (LONG_LONG) st.f_favail,
! 		    (long) st.f_flag,
! 		    (long) st.f_namemax);
! #endif
  }
  #endif /* HAVE_FSTATVFS */
--- 4341,4346 ----
  	if (res != 0)
  		return posix_error();
! 
!         return _pystatvfs_fromstructstatvfs(st);
  }
  #endif /* HAVE_FSTATVFS */
***************
*** 4241,4269 ****
  	if (res != 0)
  		return posix_error_with_filename(path);
! #if !defined(HAVE_LARGEFILE_SUPPORT)
! 	return Py_BuildValue("(llllllllll)",
! 		    (long) st.f_bsize,
! 		    (long) st.f_frsize,
! 		    (long) st.f_blocks,
! 		    (long) st.f_bfree,
! 		    (long) st.f_bavail,
! 		    (long) st.f_files,
! 		    (long) st.f_ffree,
! 		    (long) st.f_favail,
! 		    (long) st.f_flag,
! 		    (long) st.f_namemax);
! #else	/* HAVE_LARGEFILE_SUPPORT */
! 	return Py_BuildValue("(llLLLLLLll)",
! 		    (long) st.f_bsize,
! 		    (long) st.f_frsize,
! 		    (LONG_LONG) st.f_blocks,
! 		    (LONG_LONG) st.f_bfree,
! 		    (LONG_LONG) st.f_bavail,
! 		    (LONG_LONG) st.f_files,
! 		    (LONG_LONG) st.f_ffree,
! 		    (LONG_LONG) st.f_favail,
! 		    (long) st.f_flag,
! 		    (long) st.f_namemax);
! #endif
  }
  #endif /* HAVE_STATVFS */
--- 4368,4373 ----
  	if (res != 0)
  		return posix_error_with_filename(path);
! 
!         return _pystatvfs_fromstructstatvfs(st);
  }
  #endif /* HAVE_STATVFS */
***************
*** 5826,5828 ****
--- 5930,5938 ----
  		posix_putenv_garbage = PyDict_New();
  #endif
+ 
+ 	PyStructSequence_InitType(&StatResultType, &stat_result_desc);
+ 	PyDict_SetItemString(d, "stat_result", (PyObject*) &StatResultType);
+ 
+ 	PyStructSequence_InitType(&StatVFSResultType, &statvfs_result_desc);
+ 	PyDict_SetItemString(d, "statvfs_result", (PyObject*) &StatResultType);
  }

Index: timemodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/timemodule.c,v
retrieving revision 2.114
retrieving revision 2.115
diff -C2 -d -r2.114 -r2.115
*** timemodule.c	2001/09/25 13:59:01	2.114
--- timemodule.c	2001/10/18 20:34:25	2.115
***************
*** 3,6 ****
--- 3,7 ----
  
  #include "Python.h"
+ #include "structseq.h"
  
  #include <ctype.h>
***************
*** 211,227 ****
  a floating point number for subsecond precision.";
  
  static PyObject *
  tmtotuple(struct tm *p)
  {
! 	return Py_BuildValue("(iiiiiiiii)",
! 			     p->tm_year + 1900,
! 			     p->tm_mon + 1,	   /* Want January == 1 */
! 			     p->tm_mday,
! 			     p->tm_hour,
! 			     p->tm_min,
! 			     p->tm_sec,
! 			     (p->tm_wday + 6) % 7, /* Want Monday == 0 */
! 			     p->tm_yday + 1,	   /* Want January, 1 == 1 */
! 			     p->tm_isdst);
  }
  
--- 212,262 ----
  a floating point number for subsecond precision.";
  
+ static PyStructSequence_Field struct_time_type_fields[] = {
+ 	{"tm_year", NULL},
+ 	{"tm_mon", NULL},
+ 	{"tm_mday", NULL},
+ 	{"tm_hour", NULL},
+ 	{"tm_min", NULL},
+ 	{"tm_sec", NULL},
+ 	{"tm_wday", NULL},
+ 	{"tm_yday", NULL},
+ 	{"tm_isdst", NULL},
+ 	{0}
+ };
+ 
+ static PyStructSequence_Desc struct_time_type_desc = {
+ 	"struct_time",
+ 	NULL,
+ 	struct_time_type_fields,
+ 	9,
+ };
+ 	
+ static PyTypeObject StructTimeType;
+ 
  static PyObject *
  tmtotuple(struct tm *p)
  {
! 	PyObject *v = PyStructSequence_New(&StructTimeType);
! 	if (v == NULL)
! 		return NULL;
! 	
! #define SET(i,val) PyStructSequence_SET_ITEM(v, i, PyInt_FromLong((long) val))
! 
! 	SET(0, p->tm_year + 1900);
! 	SET(1, p->tm_mon + 1);	   /* Want January == 1 */
! 	SET(2, p->tm_mday);
! 	SET(3, p->tm_hour);
! 	SET(4, p->tm_min);
! 	SET(5, p->tm_sec);
! 	SET(6, (p->tm_wday + 6) % 7); /* Want Monday == 0 */
! 	SET(7, p->tm_yday + 1);	   /* Want January, 1 == 1 */
! 	SET(8, p->tm_isdst);
! #undef SET
! 	if (PyErr_Occurred()) {
! 		Py_XDECREF(v);
! 		return NULL;
! 	}
! 
! 	return v;
  }
  
***************
*** 675,678 ****
--- 710,716 ----
  #endif /* __CYGWIN__ */
  #endif /* !HAVE_TZNAME || __GLIBC__ || __CYGWIN__*/
+ 
+         PyStructSequence_InitType(&StructTimeType, &struct_time_type_desc);
+ 	PyDict_SetItemString(d, "struct_time", (PyObject*) &StructTimeType);
  }
  
***************
*** 853,856 ****
--- 891,895 ----
  #endif /* !macintosh */
  #endif /* !HAVE_SELECT */
+ 
  	return 0;
  }