summaryrefslogtreecommitdiff
path: root/packages/python/python-opendir
diff options
context:
space:
mode:
Diffstat (limited to 'packages/python/python-opendir')
-rw-r--r--packages/python/python-opendir/.mtn2git_empty0
-rw-r--r--packages/python/python-opendir/opendir.pyx149
-rw-r--r--packages/python/python-opendir/setup.py25
3 files changed, 174 insertions, 0 deletions
diff --git a/packages/python/python-opendir/.mtn2git_empty b/packages/python/python-opendir/.mtn2git_empty
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/packages/python/python-opendir/.mtn2git_empty
diff --git a/packages/python/python-opendir/opendir.pyx b/packages/python/python-opendir/opendir.pyx
new file mode 100644
index 0000000000..1ee81f7382
--- /dev/null
+++ b/packages/python/python-opendir/opendir.pyx
@@ -0,0 +1,149 @@
+##############################################################
+#
+# opendir.pyx - A class exposing the functionality of
+# =========== the opendir() family of C libary functions.
+#
+# By Gregory Ewing
+# greg.ewing@canterbury.ac.nz
+#
+# This software and derivative works created from it
+# may be used and redistributed without restriction.
+#
+##############################################################
+
+cdef extern from "sys/errno.h":
+ int errno
+
+cdef extern from "stdio.h":
+ char *strerror(int)
+
+cdef extern from "dirent.h":
+ ctypedef struct DIR
+ struct dirent:
+ int d_namlen
+ char d_name[1]
+ DIR *c_opendir "opendir" (char *)
+ int readdir_r(DIR *, dirent *, dirent **)
+ long telldir(DIR *)
+ void seekdir(DIR *, long)
+ void rewinddir(DIR *)
+ int closedir(DIR *)
+ int dirfd(DIR *)
+
+#------------------------------------------------------------------
+
+cdef class opendir:
+ """opendir(pathname) --> an open directory object
+
+ Opens a directory and provides incremental access to
+ the filenames it contains. May be used as a file-like
+ object or as an iterator.
+
+ When used as a file-like object, each call to read()
+ returns one filename, or an empty string when the end
+ of the directory is reached. The close() method should
+ be called when finished with the directory.
+
+ The close() method should also be called when used as
+ an iterator and iteration is stopped prematurely. If
+ iteration proceeds to completion, the directory is
+ closed automatically."""
+
+ cdef DIR *dir
+
+ def __cinit__(self, char *path):
+ self.dir = c_opendir(path)
+ if not self.dir:
+ raise IOError(errno, "%s: '%s'" % (strerror(errno), path))
+
+ def __dealloc__(self):
+ if self.dir:
+ closedir(self.dir)
+
+ def read(self):
+ """read() --> filename or empty string
+
+ Returns the next filename from the directory, or an empty
+ string if the end of the directory has been reached."""
+
+ cdef dirent entry, *result
+ check_open(self)
+ if readdir_r(self.dir, &entry, &result) < 0:
+ raise IOError(errno)
+ if result:
+ return entry.d_name
+ else:
+ return ""
+
+ def tell(self):
+ """tell() --> position
+
+ Returns a value representing the current position in the
+ directory, suitable for passing to tell(). Only valid for
+ this directory object as long as it remains open."""
+
+ check_open(self)
+ return telldir(self.dir)
+
+ def seek(self, long pos):
+ """seek(position)
+
+ Returns the directory to the specified position, which
+ should be a value previously returned by tell()."""
+
+ check_open(self)
+ seekdir(self.dir, pos)
+
+ def rewind(self):
+ """rewind()
+
+ Resets the position to the beginning of the directory."""
+
+ check_open(self)
+ rewinddir(self.dir)
+
+ def close(self):
+ """close()
+
+ Closes the directory and frees the underlying file descriptor."""
+
+ if self.dir:
+ if closedir(self.dir) < 0:
+ raise IOError(errno)
+ self.dir = NULL
+
+# MaxOSX doesn't seem to have dirfd, despite what the
+# man page says. :-(
+#
+# def fileno(self):
+# """fileno() --> file descriptor
+#
+# Returns the file descriptor associated with the open directory."""
+#
+# check_open(self)
+# return dirfd(self.dir)
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ """next() --> filename
+
+ Returns the next filename from the directory. If the end of the
+ directory has been reached, closes the directory and raises
+ StopIteration."""
+
+ if self.dir:
+ result = self.read()
+ if result:
+ return result
+ self.close()
+ raise StopIteration
+
+#------------------------------------------------------------------
+
+cdef int check_open(opendir d) except -1:
+ if not d.dir:
+ raise ValueError("Directory is closed")
+ return 0
+
diff --git a/packages/python/python-opendir/setup.py b/packages/python/python-opendir/setup.py
new file mode 100644
index 0000000000..d76b22c95a
--- /dev/null
+++ b/packages/python/python-opendir/setup.py
@@ -0,0 +1,25 @@
+from distutils.core import setup
+from distutils.extension import Extension
+from Cython.Distutils import build_ext
+
+setup(
+ name = 'opendir',
+ version = '0.0.1',
+ author = 'Gregory Ewing',
+ author_email = 'greg ewing at canterbury ac nz',
+ maintainer = 'Johannes "josch" Schauer',
+ maintainer_email = 'j schauer at email de',
+ description = 'Implements POSIX opendir',
+ classifiers = [
+ 'Development Status :: 4 - Beta',
+ 'Intended Audience :: Developers',
+ 'Operating System :: POSIX',
+ 'Programming Language :: Pyrex',
+ 'Topic :: Software Development :: Libraries :: Python Modules',
+ 'Topic :: System :: Filesystems'
+ ],
+ ext_modules=[
+ Extension("opendir", ["opendir.pyx"]),
+ ],
+ cmdclass = {'build_ext': build_ext}
+)