You are viewing a plain text version of this content. The canonical link for it is here.
Posted to mod_python-commits@quetz.apache.org by gr...@apache.org on 2006/08/24 14:43:00 UTC

svn commit: r434388 - in /httpd/mod_python/trunk: Doc/ dist/ lib/python/mod_python/ src/ src/include/

Author: grahamd
Date: Thu Aug 24 05:42:59 2006
New Revision: 434388

URL: http://svn.apache.org/viewvc?rev=434388&view=rev
Log:
(MODPYTHON-128) Changed req.finfo to be an object where fields of underlying
fields of apr_finfo_t structure are accessed as object attributes. Tuple
style access is still maintained for backward compatability. The req.finfo
attribute is now also writable and can be assigned with the result of calling
new functions apache.stat() and apache.lstat().


Added:
    httpd/mod_python/trunk/src/finfoobject.c   (with props)
    httpd/mod_python/trunk/src/include/finfoobject.h   (with props)
Modified:
    httpd/mod_python/trunk/Doc/appendixc.tex
    httpd/mod_python/trunk/Doc/modpython4.tex
    httpd/mod_python/trunk/dist/setup.py.in
    httpd/mod_python/trunk/lib/python/mod_python/__init__.py
    httpd/mod_python/trunk/lib/python/mod_python/apache.py
    httpd/mod_python/trunk/src/Makefile.in
    httpd/mod_python/trunk/src/_apachemodule.c
    httpd/mod_python/trunk/src/hlistobject.c
    httpd/mod_python/trunk/src/include/mod_python.h
    httpd/mod_python/trunk/src/include/mod_python.h.in
    httpd/mod_python/trunk/src/include/mpversion.h
    httpd/mod_python/trunk/src/requestobject.c

Modified: httpd/mod_python/trunk/Doc/appendixc.tex
URL: http://svn.apache.org/viewvc/httpd/mod_python/trunk/Doc/appendixc.tex?rev=434388&r1=434387&r2=434388&view=diff
==============================================================================
--- httpd/mod_python/trunk/Doc/appendixc.tex (original)
+++ httpd/mod_python/trunk/Doc/appendixc.tex Thu Aug 24 05:42:59 2006
@@ -121,13 +121,15 @@
       Apache module will be responsible for generating the content.
     \item
       (\citetitle[http://issues.apache.org/jira/browse/MODPYTHON-128]{MODPYTHON-128})
-      Added the \code{filetype} attribute of the Apache \code{finfo}
-      structure to the tuple returned when accessing \code{req.finfo}.
-      This value is accessed using \code{req.finfo[apache.FINFO_FILETYPE]}.
-      New constants \code{apache.APR_NOFILE}, \code{apache.APR_REG},
-      \code{apache.APR_DIR} etc, have been added for comparing with the
-      \code{filetype} value. The \code{req.canonical_filename} attribute
-      was also made writable.
+      Made the \code{req.canonical_filename} attribute writable. Changed
+      the \code{req.finfo} attribute from being a tuple to an actual object.
+      For backwards compatibility the attributes of the object can still be
+      accessed as if they were a tuple. New code however should access
+      the attributes as member data. The \code{req.finfo} attribute is
+      also now writable and can be assigned to using the result of calling
+      new functions \code{apache.stat()} and \code{apache.lstat()}. These
+      functions are wrappers for \code{apr_stat()} and \code{apr_lstat()}
+      respectively.
     \item
       (\citetitle[http://issues.apache.org/jira/browse/MODPYTHON-129]{MODPYTHON-129})
       When specifying multiple handlers for phases other than the content

Modified: httpd/mod_python/trunk/Doc/modpython4.tex
URL: http://svn.apache.org/viewvc/httpd/mod_python/trunk/Doc/modpython4.tex?rev=434388&r1=434387&r2=434388&view=diff
==============================================================================
--- httpd/mod_python/trunk/Doc/modpython4.tex (original)
+++ httpd/mod_python/trunk/Doc/modpython4.tex Thu Aug 24 05:42:59 2006
@@ -412,6 +412,24 @@
     parameter by calling \code{apache.exists_config_define('FOOBAR')}.
 \end{funcdesc}
 
+\begin{funcdesc}{stat}{fname, wanted}
+    This function returns an instance of an \code{mp_finfo} object
+    describing information related to the file with name \code{fname}.
+    The \code{wanted} argument describes the minimum attributes which
+    should be filled out. The resultant object can be assigned to the
+    \code{req.finfo} attribute.
+\end{funcdesc}
+
+\begin{funcdesc}{lstat}{fname, wanted}
+    This function returns an instance of an \code{mp_finfo} object
+    describing information related to the file with name \code{fname}.
+    The \code{wanted} argument describes the minimum attributes which
+    should be filled out. The resultant object can be assigned to the
+    \code{req.finfo} attribute. This function differs to {stat()} in
+    that if the file is a symlink, information about the link is returned
+    as opposed to the file the symlink points at.
+\end{funcdesc}
+
 \begin{funcdesc}{register_cleanup}{callable\optional{, data}}
   Registers a cleanup that will be performed at child shutdown time. Equivalent
   to \function{server.register_cleanup()}, except that a request object is not
@@ -1271,16 +1289,29 @@
 \end{memberdesc}
 
 \begin{memberdesc}[request]{finfo}
-  Tuple. A file information structure, analogous to POSIX stat,
-  describing the file pointed to by the URI.  \code{(mode, ino,
-    dev, nlink, uid, gid, size, atime, mtime, ctime, fname,
-    name)}. The \code{apache} module defines a set of \constant{FINFO_*}
-  constants that should be used to access elements of this
-  tuple. Example:
+  A file information object with type \code{mp_finfo}, analogous to the
+  result of the POSIX stat function, describing the
+  file pointed to by the URI. The object provides the attributes
+  \code{fname}, \code{filetype}, \code{valid}, \code{protection},
+  \code{user}, \code{group}, \code{size}, \code{inode}, \code{device},
+  \code{nlink}, \code{atime}, \code{mtime}, \code{ctime} and \code{name}.
+
+  The attribute may be assigned to using the result of \code{apache.stat()}
+  or \code{apache.lstat()}. For example:
+
   \begin{verbatim}
-fname = req.finfo[apache.FINFO_FNAME]
+if req.finfo.filetype == apache.APR_DIR:
+  req.filename = posixpath.join(req.filename, 'index.html')
+  req.finfo = apache.stat(req.filename, apache.APR_FINFO_MIN)
+  \end{verbatim}
+
+  For backward compatability, the object can also be accessed as if it
+  were a tuple. The \code{apache} module defines a set of \constant{FINFO_*}
+  constants that should be used to access elements of this tuple.
+
+  \begin{verbatim}
+user = req.finfo[apache.FINFO_USER]
   \end{verbatim}
-  \emph{(Read-Only})
 \end{memberdesc}
 
 \begin{memberdesc}[request]{parsed_uri}

Modified: httpd/mod_python/trunk/dist/setup.py.in
URL: http://svn.apache.org/viewvc/httpd/mod_python/trunk/dist/setup.py.in?rev=434388&r1=434387&r2=434388&view=diff
==============================================================================
--- httpd/mod_python/trunk/dist/setup.py.in (original)
+++ httpd/mod_python/trunk/dist/setup.py.in Thu Aug 24 05:42:59 2006
@@ -115,7 +115,7 @@
 
 modpy_src_files = ("mod_python.c", "_apachemodule.c", "connobject.c", "filterobject.c",
                    "hlist.c", "hlistobject.c", "requestobject.c", "serverobject.c", "tableobject.c",
-                   "util.c")
+                   "util.c", "finfoobject.c")
 
 class finallist(list):
   """this represents a list that cannot be appended to..."""

Modified: httpd/mod_python/trunk/lib/python/mod_python/__init__.py
URL: http://svn.apache.org/viewvc/httpd/mod_python/trunk/lib/python/mod_python/__init__.py?rev=434388&r1=434387&r2=434388&view=diff
==============================================================================
--- httpd/mod_python/trunk/lib/python/mod_python/__init__.py (original)
+++ httpd/mod_python/trunk/lib/python/mod_python/__init__.py Thu Aug 24 05:42:59 2006
@@ -20,5 +20,5 @@
 __all__ = ["apache", "cgihandler", "psp",
            "publisher", "util", "python22"]
 
-version = "3.3.0-dev-20060820"
+version = "3.3.0-dev-20060824"
 

Modified: httpd/mod_python/trunk/lib/python/mod_python/apache.py
URL: http://svn.apache.org/viewvc/httpd/mod_python/trunk/lib/python/mod_python/apache.py?rev=434388&r1=434387&r2=434388&view=diff
==============================================================================
--- httpd/mod_python/trunk/lib/python/mod_python/apache.py (original)
+++ httpd/mod_python/trunk/lib/python/mod_python/apache.py Thu Aug 24 05:42:59 2006
@@ -944,6 +944,8 @@
 server_root = _apache.server_root
 mpm_query = _apache.mpm_query
 exists_config_define = _apache.exists_config_define
+stat = _apache.stat
+lstat = _apache.lstat
 
 ## Some constants
 
@@ -1067,7 +1069,6 @@
 FINFO_FNAME = 10
 FINFO_NAME = 11
 FINFO_FILETYPE = 12
-#FINFO_FILEHAND = 14
 
 # the req.parsed_uri
 URI_SCHEME = 0
@@ -1171,3 +1172,28 @@
 APR_LNK = _apache.APR_LNK
 APR_SOCK = _apache.APR_SOCK
 APR_UNKFILE = _apache.APR_UNKFILE
+
+# for apache.stat()
+APR_FINFO_LINK = 0x00000001 # Stat the link not the file itself if it is a link
+APR_FINFO_MTIME = 0x00000010 # Modification Time
+APR_FINFO_CTIME = 0x00000020 # Creation or inode-changed time
+APR_FINFO_ATIME = 0x00000040 # Access Time
+APR_FINFO_SIZE = 0x00000100 # Size of the file
+APR_FINFO_CSIZE = 0x00000200 # Storage size consumed by the file
+APR_FINFO_DEV = 0x00001000 # Device
+APR_FINFO_INODE = 0x00002000 # Inode
+APR_FINFO_NLINK = 0x00004000 # Number of links
+APR_FINFO_TYPE = 0x00008000 # Type
+APR_FINFO_USER = 0x00010000 # User
+APR_FINFO_GROUP = 0x00020000 # Group
+APR_FINFO_UPROT = 0x00100000 # User protection bits
+APR_FINFO_GPROT = 0x00200000 # Group protection bits
+APR_FINFO_WPROT = 0x00400000 # World protection bits
+APR_FINFO_ICASE = 0x01000000 # if dev is case insensitive
+APR_FINFO_NAME = 0x02000000 # ->name in proper case
+APR_FINFO_MIN = 0x00008170 # type, mtime, ctime, atime, size
+APR_FINFO_IDENT = 0x00003000 # dev and inode
+APR_FINFO_OWNER = 0x00030000 # user and group
+APR_FINFO_PROT = 0x00700000 # all protections
+APR_FINFO_NORM = 0x0073b170 # an atomic unix apr_stat()
+APR_FINFO_DIRENT = 0x02000000 # an atomic unix apr_dir_read()

Modified: httpd/mod_python/trunk/src/Makefile.in
URL: http://svn.apache.org/viewvc/httpd/mod_python/trunk/src/Makefile.in?rev=434388&r1=434387&r2=434388&view=diff
==============================================================================
--- httpd/mod_python/trunk/src/Makefile.in (original)
+++ httpd/mod_python/trunk/src/Makefile.in Thu Aug 24 05:42:59 2006
@@ -30,7 +30,8 @@
 srcdir=.
 
 SRCS=	mod_python.c _apachemodule.c requestobject.c tableobject.c util.c \
-		serverobject.c connobject.c filterobject.c hlist.c hlistobject.c
+		serverobject.c connobject.c filterobject.c hlist.c \
+		hlistobject.c finfoobject.c
 
 all:	@ALL@
 

Modified: httpd/mod_python/trunk/src/_apachemodule.c
URL: http://svn.apache.org/viewvc/httpd/mod_python/trunk/src/_apachemodule.c?rev=434388&r1=434387&r2=434388&view=diff
==============================================================================
--- httpd/mod_python/trunk/src/_apachemodule.c (original)
+++ httpd/mod_python/trunk/src/_apachemodule.c Thu Aug 24 05:42:59 2006
@@ -688,6 +688,72 @@
     }
 }
 
+/**
+ ** mp_stat(fname, wanted)
+ **
+ *  Wrapper for apr_stat().
+ */
+
+static PyObject *mp_stat(PyObject *self, PyObject *args)
+{
+    char *fname = NULL;
+    apr_int32_t wanted = 0;
+    finfoobject* finfo;
+    apr_status_t result;
+
+    if (! PyArg_ParseTuple(args, "si", &fname, &wanted))
+        return NULL; 
+
+    finfo = (finfoobject *)MpFinfo_New();
+
+    fname = apr_pstrdup(finfo->pool, fname);
+
+    result = apr_stat(finfo->finfo, fname, wanted, finfo->pool);
+
+    if (result == APR_INCOMPLETE || result == APR_SUCCESS)
+        return (PyObject *)finfo;
+
+    Py_DECREF(finfo);
+
+    PyErr_SetObject(PyExc_OSError,
+                    Py_BuildValue("is", result, "apr_stat() failed"));
+
+    return NULL;
+}
+
+/**
+ ** mp_lstat(fname, wanted)
+ **
+ *  Wrapper for apr_lstat().
+ */
+
+static PyObject *mp_lstat(PyObject *self, PyObject *args)
+{
+    char *fname = NULL;
+    apr_int32_t wanted = 0;
+    finfoobject* finfo;
+    apr_status_t result;
+
+    if (! PyArg_ParseTuple(args, "si", &fname, &wanted))
+        return NULL; 
+
+    finfo = (finfoobject *)MpFinfo_New();
+
+    fname = apr_pstrdup(finfo->pool, fname);
+
+    result = apr_lstat(finfo->finfo, fname, wanted, finfo->pool);
+
+    if (result == APR_INCOMPLETE || result == APR_SUCCESS)
+        return (PyObject *)finfo;
+
+    Py_DECREF(finfo);
+
+    PyErr_SetObject(PyExc_OSError,
+                    Py_BuildValue("is", result, "apr_stat() failed"));
+
+    return NULL;
+}
+
 /* methods of _apache */
 struct PyMethodDef _apache_module_methods[] = {
     {"config_tree",           (PyCFunction)config_tree,          METH_NOARGS},
@@ -698,6 +764,8 @@
     {"server_root",           (PyCFunction)server_root,          METH_NOARGS},
     {"register_cleanup",      (PyCFunction)register_cleanup,     METH_VARARGS},
     {"exists_config_define",  (PyCFunction)exists_config_define, METH_VARARGS},
+    {"stat",                  (PyCFunction)mp_stat,              METH_VARARGS},
+    {"lstat",                 (PyCFunction)mp_lstat,             METH_VARARGS},
     {"_global_lock",          (PyCFunction)_global_lock,         METH_VARARGS},
     {"_global_trylock",       (PyCFunction)_global_trylock,      METH_VARARGS},
     {"_global_unlock",        (PyCFunction)_global_unlock,       METH_VARARGS},

Added: httpd/mod_python/trunk/src/finfoobject.c
URL: http://svn.apache.org/viewvc/httpd/mod_python/trunk/src/finfoobject.c?rev=434388&view=auto
==============================================================================
--- httpd/mod_python/trunk/src/finfoobject.c (added)
+++ httpd/mod_python/trunk/src/finfoobject.c Thu Aug 24 05:42:59 2006
@@ -0,0 +1,386 @@
+/*
+ * Copyright 2004 Apache Software Foundation 
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you
+ * may not use this file except in compliance with the License.  You
+ * may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ *
+ * Originally developed by Gregory Trubetskoy.
+ *
+ *
+ * finfoobject.c 
+ *
+ * $Id$
+ *
+ */
+
+#include "mod_python.h"
+
+/**
+ **     MpFinfo_FromFinfo
+ **
+ *      This routine creates a Python finfoobject given an Apache
+ *      finfo pointer.
+ *
+ */
+
+PyObject * MpFinfo_FromFinfo(apr_finfo_t *f)
+{
+    finfoobject *result;
+
+    result = PyObject_New(finfoobject, &MpFinfo_Type);
+    if (! result)
+        return PyErr_NoMemory();
+
+    result->finfo = f;
+    result->pool = NULL;
+
+    return (PyObject *)result;
+}
+
+/** 
+ ** MpFinfo_New
+ **
+ *  This returns a new object of built-in type finfo.
+ *
+ *  NOTE: The apr_finfo_t gets greated in its own pool, which lives
+ *  throught the life of the finfoobject.
+ *
+ */
+
+PyObject * MpFinfo_New()
+{
+    finfoobject *f;
+    apr_pool_t *p;
+
+    /* XXX need second arg abort function to report mem error */
+    apr_pool_create_ex(&p, NULL, NULL, NULL);
+
+    f = (finfoobject *)MpFinfo_FromFinfo(apr_pcalloc(p, sizeof(apr_finfo_t)));
+
+    /* remember the pointer to our own pool */
+    f->pool = p;
+
+    return (PyObject *)f;
+}
+
+/**
+ ** finfo_dealloc
+ **
+ *      Frees finfo's memory
+ */
+
+static void finfo_dealloc(register finfoobject *self)
+{  
+    if (MpFinfo_Check(self)) {
+        if (self->pool) 
+            apr_pool_destroy(self->pool);
+        PyObject_Del(self);
+    }
+    else
+        self->ob_type->tp_free((PyObject *)self);
+}
+
+/**
+ ** finfo_getattr
+ **
+ *  Get finfo object attributes
+ *
+ */
+
+static PyObject * finfo_getattr(finfoobject *self, char *name)
+{
+    if (strcmp(name, "fname") == 0) {
+        if (self->finfo->fname)
+            return PyString_FromString(self->finfo->fname);
+    }
+    else if (strcmp(name, "filetype") == 0) {
+        return PyInt_FromLong(self->finfo->filetype);
+    }
+    else if (strcmp(name, "valid") == 0) {
+        if (self->finfo->filetype == APR_NOFILE) {
+            Py_INCREF(Py_None);
+            return Py_None;
+        }
+        return PyInt_FromLong(self->finfo->valid);
+    }
+    else if (strcmp(name, "protection") == 0) {
+        if (self->finfo->filetype == APR_NOFILE) {
+            Py_INCREF(Py_None);
+            return Py_None;
+        }
+        if (self->finfo->valid & APR_FINFO_PROT)
+            return PyInt_FromLong(self->finfo->protection);
+    }
+    else if (strcmp(name, "user") == 0) {
+        if (self->finfo->filetype == APR_NOFILE) {
+            Py_INCREF(Py_None);
+            return Py_None;
+        }
+        if (self->finfo->valid & APR_FINFO_USER)
+            return PyInt_FromLong(self->finfo->user);
+    }
+    else if (strcmp(name, "group") == 0) {
+        if (self->finfo->filetype == APR_NOFILE) {
+            Py_INCREF(Py_None);
+            return Py_None;
+        }
+        if (self->finfo->valid & APR_FINFO_GROUP)
+            return PyInt_FromLong(self->finfo->group);
+    }
+    else if (strcmp(name, "inode") == 0) {
+        if (self->finfo->filetype == APR_NOFILE) {
+            Py_INCREF(Py_None);
+            return Py_None;
+        }
+        if (self->finfo->valid & APR_FINFO_INODE)
+            return PyInt_FromLong(self->finfo->inode);
+    }
+    else if (strcmp(name, "device") == 0) {
+        if (self->finfo->filetype == APR_NOFILE) {
+            Py_INCREF(Py_None);
+            return Py_None;
+        }
+        if (self->finfo->valid & APR_FINFO_DEV)
+            return PyInt_FromLong(self->finfo->device);
+    }
+    else if (strcmp(name, "nlink") == 0) {
+        if (self->finfo->filetype == APR_NOFILE) {
+            Py_INCREF(Py_None);
+            return Py_None;
+        }
+        if (self->finfo->valid & APR_FINFO_NLINK)
+            return PyInt_FromLong(self->finfo->nlink);
+    }
+    else if (strcmp(name, "size") == 0) {
+        if (self->finfo->filetype == APR_NOFILE) {
+            Py_INCREF(Py_None);
+            return Py_None;
+        }
+        if (self->finfo->valid & APR_FINFO_SIZE) {
+            if (sizeof(apr_off_t) == sizeof(LONG_LONG)) {
+                return PyLong_FromLongLong(self->finfo->size);
+            }
+            else {
+                return PyLong_FromLong(self->finfo->size);
+            }
+        }
+    }
+    else if (strcmp(name, "atime") == 0) {
+        if (self->finfo->filetype == APR_NOFILE) {
+            Py_INCREF(Py_None);
+            return Py_None;
+        }
+        if (self->finfo->valid & APR_FINFO_ATIME)
+            return PyInt_FromLong(self->finfo->atime*0.000001);
+    }
+    else if (strcmp(name, "mtime") == 0) {
+        if (self->finfo->filetype == APR_NOFILE) {
+            Py_INCREF(Py_None);
+            return Py_None;
+        }
+        if (self->finfo->valid & APR_FINFO_MTIME)
+            return PyInt_FromLong(self->finfo->mtime*0.000001);
+    }
+    else if (strcmp(name, "ctime") == 0) {
+        if (self->finfo->filetype == APR_NOFILE) {
+            Py_INCREF(Py_None);
+            return Py_None;
+        }
+        if (self->finfo->valid & APR_FINFO_CTIME)
+            return PyInt_FromLong(self->finfo->ctime*0.000001);
+    }
+    else if (strcmp(name, "name") == 0) {
+        if (self->finfo->filetype == APR_NOFILE) {
+            Py_INCREF(Py_None);
+            return Py_None;
+        }
+        if (self->finfo->valid & APR_FINFO_NAME)
+            return PyString_FromString(self->finfo->name);
+    }
+    else {
+        PyErr_Format(PyExc_AttributeError,
+                     "class 'mp_finfo' has no attribute '%.400s'", name);
+        return NULL;
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject*
+finfoseq_item(finfoobject *self, int i)
+{
+    if (i < 0 || i >= 12) {
+        PyErr_SetString(PyExc_IndexError, "tuple index out of range");
+        return NULL;
+    }
+
+    switch (i) {
+        case 0: {
+          return finfo_getattr(self, "protection");
+        }
+        case 1: {
+            return finfo_getattr(self, "inode");
+        }
+        case 2: {
+            return finfo_getattr(self, "device");
+        }
+        case 3: {
+            return finfo_getattr(self, "nlink");
+        }
+        case 4: {
+            return finfo_getattr(self, "user");
+        }
+        case 5: {
+            return finfo_getattr(self, "group");
+        }
+        case 6: {
+            return finfo_getattr(self, "size");
+        }
+        case 7: {
+            return finfo_getattr(self, "atime");
+        }
+        case 8: {
+            return finfo_getattr(self, "mtime");
+        }
+        case 9: {
+            return finfo_getattr(self, "ctime");
+        }
+        case 10: {
+            return finfo_getattr(self, "fname");
+        }
+        case 11: {
+            return finfo_getattr(self, "name");
+        }
+        case 12: {
+            return finfo_getattr(self, "filetype");
+        }
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PySequenceMethods finfoseq_as_sequence = {
+        0,
+        0,                                      /* sq_concat */
+        0,                                      /* sq_repeat */
+        (intargfunc)finfoseq_item,              /* sq_item */
+        0,                                      /* sq_slice */
+        0,                                      /* sq_ass_item */
+        0,                                      /* sq_ass_slice */
+        0,                                      /* sq_contains */
+};
+
+/**
+ ** finfo_repr
+ **
+ *
+ */
+
+static PyObject *finfo_repr(finfoobject *self)
+{
+    PyObject *s = PyString_FromString("{");
+    PyObject *t = NULL;
+
+    PyString_ConcatAndDel(&s, PyString_FromString("'fname': "));
+    t = finfo_getattr(self, "fname");
+    PyString_ConcatAndDel(&s, PyObject_Repr(t));
+    Py_XDECREF(t);
+
+    PyString_ConcatAndDel(&s, PyString_FromString(", 'filetype': "));
+    t = finfo_getattr(self, "filetype");
+    PyString_ConcatAndDel(&s, PyObject_Repr(t));
+    Py_XDECREF(t);
+
+    PyString_ConcatAndDel(&s, PyString_FromString(", 'valid': "));
+    t = finfo_getattr(self, "valid");
+    PyString_ConcatAndDel(&s, PyObject_Repr(t));
+    Py_XDECREF(t);
+
+    PyString_ConcatAndDel(&s, PyString_FromString(", 'protection': "));
+    t = finfo_getattr(self, "protection");
+    PyString_ConcatAndDel(&s, PyObject_Repr(t));
+    Py_XDECREF(t);
+
+    PyString_ConcatAndDel(&s, PyString_FromString(", 'user': "));
+    t = finfo_getattr(self, "user");
+    PyString_ConcatAndDel(&s, PyObject_Repr(t));
+    Py_XDECREF(t);
+
+    PyString_ConcatAndDel(&s, PyString_FromString(", 'group': "));
+    t = finfo_getattr(self, "group");
+    PyString_ConcatAndDel(&s, PyObject_Repr(t));
+    Py_XDECREF(t);
+
+    PyString_ConcatAndDel(&s, PyString_FromString(", 'size': "));
+    t = finfo_getattr(self, "size");
+    PyString_ConcatAndDel(&s, PyObject_Repr(t));
+    Py_XDECREF(t);
+
+    PyString_ConcatAndDel(&s, PyString_FromString(", 'inode': "));
+    t = finfo_getattr(self, "inode");
+    PyString_ConcatAndDel(&s, PyObject_Repr(t));
+    Py_XDECREF(t);
+
+    PyString_ConcatAndDel(&s, PyString_FromString(", 'device': "));
+    t = finfo_getattr(self, "device");
+    PyString_ConcatAndDel(&s, PyObject_Repr(t));
+    Py_XDECREF(t);
+
+    PyString_ConcatAndDel(&s, PyString_FromString(", 'nlink': "));
+    t = finfo_getattr(self, "nlink");
+    PyString_ConcatAndDel(&s, PyObject_Repr(t));
+    Py_XDECREF(t);
+
+    PyString_ConcatAndDel(&s, PyString_FromString(", 'atime': "));
+    t = finfo_getattr(self, "atime");
+    PyString_ConcatAndDel(&s, PyObject_Repr(t));
+    Py_XDECREF(t);
+
+    PyString_ConcatAndDel(&s, PyString_FromString(", 'mtime': "));
+    t = finfo_getattr(self, "mtime");
+    PyString_ConcatAndDel(&s, PyObject_Repr(t));
+    Py_XDECREF(t);
+
+    PyString_ConcatAndDel(&s, PyString_FromString(", 'ctime': "));
+    t = finfo_getattr(self, "ctime");
+    PyString_ConcatAndDel(&s, PyObject_Repr(t));
+    Py_XDECREF(t);
+
+    PyString_ConcatAndDel(&s, PyString_FromString(", 'name': "));
+    t = finfo_getattr(self, "name");
+    PyString_ConcatAndDel(&s, PyObject_Repr(t));
+    Py_XDECREF(t);
+
+    PyString_ConcatAndDel(&s, PyString_FromString("}"));
+
+    return s;
+}
+
+PyTypeObject MpFinfo_Type = {
+    PyObject_HEAD_INIT(NULL)
+    0,
+    "mp_finfo",
+    sizeof(finfoobject),
+    0,
+    (destructor)finfo_dealloc,          /* tp_dealloc */
+    0,                                  /* tp_print */
+    (getattrfunc)finfo_getattr,         /*tp_getattr*/
+    0,                                  /*tp_setattr*/
+    0,                                  /* tp_compare */
+    (reprfunc)finfo_repr,               /*tp_repr*/
+    0,                                  /* tp_as_number */
+    &finfoseq_as_sequence,              /* tp_as_sequence */
+    0,                                  /* tp_as_mapping */
+    0,                                  /* tp_hash */
+};

Propchange: httpd/mod_python/trunk/src/finfoobject.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpd/mod_python/trunk/src/finfoobject.c
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: httpd/mod_python/trunk/src/hlistobject.c
URL: http://svn.apache.org/viewvc/httpd/mod_python/trunk/src/hlistobject.c?rev=434388&r1=434387&r2=434388&view=diff
==============================================================================
--- httpd/mod_python/trunk/src/hlistobject.c (original)
+++ httpd/mod_python/trunk/src/hlistobject.c Thu Aug 24 05:42:59 2006
@@ -136,21 +136,22 @@
 
 static PyObject *hlist_repr(hlistobject *self)
 {
+    PyObject *t;
     PyObject *s = PyString_FromString("{");
-    PyObject *repr = NULL;
     if (self->head->handler) {
-        PyString_ConcatAndDel(&s, PyString_FromString("'handler:'"));
-        PyString_ConcatAndDel(&s, PyString_FromString(self->head->handler));
-        PyString_ConcatAndDel(&s, PyString_FromString("'"));
+        PyString_ConcatAndDel(&s, PyString_FromString("'handler':"));
+        t = PyString_FromString(self->head->handler);
+        PyString_ConcatAndDel(&s, PyObject_Repr(t));
+        Py_XDECREF(t);
     } else if (self->head->callable) {
-        PyString_ConcatAndDel(&s, PyString_FromString("'handler:'"));
+        PyString_ConcatAndDel(&s, PyString_FromString("'handler':"));
         PyString_ConcatAndDel(&s, PyObject_Repr(self->head->callable));
-        PyString_ConcatAndDel(&s, PyString_FromString("'"));
     }
     if (self->head->directory) {
-        PyString_ConcatAndDel(&s, PyString_FromString(",'directory':'"));
-        PyString_ConcatAndDel(&s, PyString_FromString(self->head->directory));
-        PyString_ConcatAndDel(&s, PyString_FromString("'"));
+        PyString_ConcatAndDel(&s, PyString_FromString(",'directory':"));
+        t = PyString_FromString(self->head->directory);
+        PyString_ConcatAndDel(&s, PyObject_Repr(t));
+        Py_XDECREF(t);
     }
     PyString_ConcatAndDel(&s, PyString_FromString(",'silent':"));
     if (self->head->silent)

Added: httpd/mod_python/trunk/src/include/finfoobject.h
URL: http://svn.apache.org/viewvc/httpd/mod_python/trunk/src/include/finfoobject.h?rev=434388&view=auto
==============================================================================
--- httpd/mod_python/trunk/src/include/finfoobject.h (added)
+++ httpd/mod_python/trunk/src/include/finfoobject.h Thu Aug 24 05:42:59 2006
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2004 Apache Software Foundation 
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you
+ * may not use this file except in compliance with the License.  You
+ * may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ *
+ * Originally developed by Gregory Trubetskoy.
+ *
+ *
+ * finfoobject.h 
+ *
+ * $Id$
+ *
+ */
+
+#ifndef Mp_FINFOOBJECT_H
+#define Mp_FINFOOBJECT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+    typedef struct finfoobject {
+        PyObject_HEAD
+        apr_pool_t      *pool;
+        apr_finfo_t     *finfo;
+    } finfoobject;
+
+    extern DL_IMPORT(PyTypeObject) MpFinfo_Type;
+    
+#define MpFinfo_Check(op) ((op)->ob_type == &MpFinfo_Type)
+    
+    extern DL_IMPORT(PyObject *) MpFinfo_FromFinfo Py_PROTO((apr_finfo_t *f));
+    extern DL_IMPORT(PyObject *) MpFinfo_New Py_PROTO((void));
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Mp_FINFOOBJECT_H */

Propchange: httpd/mod_python/trunk/src/include/finfoobject.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpd/mod_python/trunk/src/include/finfoobject.h
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: httpd/mod_python/trunk/src/include/mod_python.h
URL: http://svn.apache.org/viewvc/httpd/mod_python/trunk/src/include/mod_python.h?rev=434388&r1=434387&r2=434388&view=diff
==============================================================================
--- httpd/mod_python/trunk/src/include/mod_python.h (original)
+++ httpd/mod_python/trunk/src/include/mod_python.h Thu Aug 24 05:42:59 2006
@@ -106,6 +106,7 @@
 #include "requestobject.h"
 #include "filterobject.h"
 #include "_pspmodule.h"
+#include "finfoobject.h"
 
 /** Things specific to mod_python, as an Apache module **/
 

Modified: httpd/mod_python/trunk/src/include/mod_python.h.in
URL: http://svn.apache.org/viewvc/httpd/mod_python/trunk/src/include/mod_python.h.in?rev=434388&r1=434387&r2=434388&view=diff
==============================================================================
--- httpd/mod_python/trunk/src/include/mod_python.h.in (original)
+++ httpd/mod_python/trunk/src/include/mod_python.h.in Thu Aug 24 05:42:59 2006
@@ -106,6 +106,7 @@
 #include "requestobject.h"
 #include "filterobject.h"
 #include "_pspmodule.h"
+#include "finfoobject.h"
 
 /** Things specific to mod_python, as an Apache module **/
 

Modified: httpd/mod_python/trunk/src/include/mpversion.h
URL: http://svn.apache.org/viewvc/httpd/mod_python/trunk/src/include/mpversion.h?rev=434388&r1=434387&r2=434388&view=diff
==============================================================================
--- httpd/mod_python/trunk/src/include/mpversion.h (original)
+++ httpd/mod_python/trunk/src/include/mpversion.h Thu Aug 24 05:42:59 2006
@@ -1,5 +1,5 @@
 #define MPV_MAJOR 3
 #define MPV_MINOR 3
 #define MPV_PATCH 0
-#define MPV_BUILD 20060820
-#define MPV_STRING "3.3.0-dev-20060820"
+#define MPV_BUILD 20060824
+#define MPV_STRING "3.3.0-dev-20060824"

Modified: httpd/mod_python/trunk/src/requestobject.c
URL: http://svn.apache.org/viewvc/httpd/mod_python/trunk/src/requestobject.c?rev=434388&r1=434387&r2=434388&view=diff
==============================================================================
--- httpd/mod_python/trunk/src/requestobject.c (original)
+++ httpd/mod_python/trunk/src/requestobject.c Thu Aug 24 05:42:59 2006
@@ -1805,6 +1805,21 @@
             apr_pstrdup(self->request_rec->pool, PyString_AsString(val));
         return 0;
     }
+    else if (strcmp(name, "finfo") == 0) {
+        finfoobject *f;
+        if (! MpFinfo_Check(val)) {
+            PyErr_SetString(PyExc_TypeError, "finfo must be a finfoobject");
+            return -1;
+        }
+        f = (finfoobject *)val;
+        self->request_rec->finfo = *f->finfo;
+        self->request_rec->finfo.fname = apr_pstrdup(self->request_rec->pool,
+                                                      f->finfo->fname);
+        self->request_rec->finfo.name = apr_pstrdup(self->request_rec->pool,
+                                                      f->finfo->name);
+
+        return 0;
+    }
     
     return PyMember_SetOne((char*)self->request_rec, 
                            find_memberdef(request_rec_mbrs, (char*)name),
@@ -1888,7 +1903,7 @@
     apr_finfo_t *fi = 
         (apr_finfo_t *)((char *)self->request_rec + md->offset);
 
-    return tuple_from_finfo(fi);
+    return MpFinfo_FromFinfo(fi);
 }
 
 /**
@@ -2003,7 +2018,7 @@
     {"canonical_filename", (getter)getreq_recmbr, (setter)setreq_recmbr, "The true filename (req.filename is canonicalized if they dont match)", "canonical_filename"},
     {"path_info",     (getter)getreq_recmbr, (setter)setreq_recmbr, "Path_info, if any", "path_info"},
     {"args",          (getter)getreq_recmbr, NULL, "QUERY_ARGS, if any", "args"},
-    {"finfo",         (getter)getreq_rec_fi, NULL, "File information", "finfo"},
+    {"finfo",         (getter)getreq_rec_fi, (setter)setreq_recmbr, "File information", "finfo"},
     {"parsed_uri",    (getter)getreq_rec_uri, NULL, "Components of URI", "parsed_uri"},
     {"used_path_info", (getter)getreq_recmbr, NULL, "Flag to accept or reject path_info on current request", "used_path_info"},
     {"headers_in", (getter)getreq_recmbr, NULL, "Incoming headers", "headers_in"},