[pypy-commit] pypy default: _pwd_cffi, to make it a bit more portable than the ctypes version

arigo noreply at buildbot.pypy.org
Tue May 19 22:39:05 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r77414:1291bd5dee42
Date: 2015-05-19 22:39 +0200
http://bitbucket.org/pypy/pypy/changeset/1291bd5dee42/

Log:	_pwd_cffi, to make it a bit more portable than the ctypes version

diff --git a/lib_pypy/_pwd_build.py b/lib_pypy/_pwd_build.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_pwd_build.py
@@ -0,0 +1,38 @@
+from cffi import FFI
+
+ffi = FFI()
+
+ffi.set_source("_pwd_cffi", """
+#include <sys/types.h>
+#include <pwd.h>
+""")
+
+
+ffi.cdef("""
+
+typedef int uid_t;
+typedef int gid_t;
+
+struct passwd {
+    char *pw_name;
+    char *pw_passwd;
+    uid_t pw_uid;
+    gid_t pw_gid;
+    char *pw_gecos;
+    char *pw_dir;
+    char *pw_shell;
+    ...;
+};
+
+struct passwd *getpwuid(uid_t uid);
+struct passwd *getpwnam(const char *name);
+
+struct passwd *getpwent(void);
+void setpwent(void);
+void endpwent(void);
+
+""")
+
+
+if __name__ == "__main__":
+    ffi.compile()
diff --git a/lib_pypy/pwd.py b/lib_pypy/pwd.py
--- a/lib_pypy/pwd.py
+++ b/lib_pypy/pwd.py
@@ -10,65 +10,13 @@
 exception is raised if the entry asked for cannot be found.
 """
 
-import sys
-if sys.platform == 'win32':
-    raise ImportError("No pwd module on Windows")
-
-from ctypes_support import standard_c_lib as libc
-from ctypes import Structure, POINTER, c_int, c_char_p, c_long
+from _pwd_cffi import ffi, lib
 from _structseq import structseqtype, structseqfield
 
 try: from __pypy__ import builtinify
 except ImportError: builtinify = lambda f: f
 
 
-uid_t = c_int
-gid_t = c_int
-time_t = c_long
-
-if sys.platform == 'darwin':
-    class passwd(Structure):
-        _fields_ = (
-            ("pw_name", c_char_p),
-            ("pw_passwd", c_char_p),
-            ("pw_uid", uid_t),
-            ("pw_gid", gid_t),
-            ("pw_change", time_t),
-            ("pw_class", c_char_p),
-            ("pw_gecos", c_char_p),
-            ("pw_dir", c_char_p),
-            ("pw_shell", c_char_p),
-            ("pw_expire", time_t),
-            ("pw_fields", c_int),
-        )
-        def __iter__(self):
-            yield self.pw_name
-            yield self.pw_passwd
-            yield self.pw_uid
-            yield self.pw_gid
-            yield self.pw_gecos
-            yield self.pw_dir
-            yield self.pw_shell
-else:
-    class passwd(Structure):
-        _fields_ = (
-            ("pw_name", c_char_p),
-            ("pw_passwd", c_char_p),
-            ("pw_uid", uid_t),
-            ("pw_gid", gid_t),
-            ("pw_gecos", c_char_p),
-            ("pw_dir", c_char_p),
-            ("pw_shell", c_char_p),
-        )
-        def __iter__(self):
-            yield self.pw_name
-            yield self.pw_passwd
-            yield self.pw_uid
-            yield self.pw_gid
-            yield self.pw_gecos
-            yield self.pw_dir
-            yield self.pw_shell
-
 class struct_passwd:
     """
     pwd.struct_passwd: Results from getpw*() routines.
@@ -87,32 +35,16 @@
     pw_dir = structseqfield(5)
     pw_shell = structseqfield(6)
 
-passwd_p = POINTER(passwd)
 
-_getpwuid = libc.getpwuid
-_getpwuid.argtypes = (uid_t,)
-_getpwuid.restype = passwd_p
-
-_getpwnam = libc.getpwnam
-_getpwnam.argtypes = (c_char_p,)
-_getpwnam.restype = passwd_p
-
-_setpwent = libc.setpwent
-_setpwent.argtypes = None
-_setpwent.restype = None
-
-_getpwent = libc.getpwent
-_getpwent.argtypes = None
-_getpwent.restype = passwd_p
-
-_endpwent = libc.endpwent
-_endpwent.argtypes = None
-_endpwent.restype = None
-
- at builtinify
-def mkpwent(pw):
-    pw = pw.contents
-    return struct_passwd(pw)
+def _mkpwent(pw):
+    return struct_passwd([
+        ffi.string(pw.pw_name),
+        ffi.string(pw.pw_passwd),
+        pw.pw_uid,
+        pw.pw_gid,
+        ffi.string(pw.pw_gecos),
+        ffi.string(pw.pw_dir),
+        ffi.string(pw.pw_shell)])
 
 @builtinify
 def getpwuid(uid):
@@ -122,10 +54,10 @@
     Return the password database entry for the given numeric user ID.
     See pwd.__doc__ for more on password database entries.
     """
-    pw = _getpwuid(uid)
+    pw = lib.getpwuid(uid)
     if not pw:
         raise KeyError("getpwuid(): uid not found: %s" % uid)
-    return mkpwent(pw)
+    return _mkpwent(pw)
 
 @builtinify
 def getpwnam(name):
@@ -137,10 +69,10 @@
     """
     if not isinstance(name, str):
         raise TypeError("expected string")
-    pw = _getpwnam(name)
+    pw = lib.getpwnam(name)
     if not pw:
         raise KeyError("getpwname(): name not found: %s" % name)
-    return mkpwent(pw)
+    return _mkpwent(pw)
 
 @builtinify
 def getpwall():
@@ -150,13 +82,13 @@
     See pwd.__doc__ for more on password database entries.
     """
     users = []
-    _setpwent()
+    lib.setpwent()
     while True:
-        pw = _getpwent()
+        pw = lib.getpwent()
         if not pw:
             break
-        users.append(mkpwent(pw))
-    _endpwent()
+        users.append(_mkpwent(pw))
+    lib.endpwent()
     return users
 
 __all__ = ('struct_passwd', 'getpwuid', 'getpwnam', 'getpwall')
@@ -173,4 +105,3 @@
     print("All:")
     for pw in getpwall():
         print(pw)
-
diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py
--- a/pypy/tool/release/package.py
+++ b/pypy/tool/release/package.py
@@ -55,7 +55,8 @@
                   ignore_errors=True)
     modules = ['_sqlite3_build.py', '_audioop_build.py']
     if not sys.platform == 'win32':
-        modules += ['_curses_build.py', '_syslog_build.py', '_gdbm_build.py']
+        modules += ['_curses_build.py', '_syslog_build.py', '_gdbm_build.py',
+                    '_pwd_build.py']
     if not options.no_tk:
         modules.append('_tkinter/tklib_build.py')
     for module in modules:


More information about the pypy-commit mailing list