import stat
import os

import _fdinfo
get_open_fds = _fdinfo.get_open_fds

def stat_pid_fd(pid, fd):
    # TODO: Implement for darwin
    return os.stat("/proc/%d/fd/%d" % (pid, fd))


_TYPE_LOOKUP = {
    000: "anon_inode",
    stat.S_IFBLK: "block",
    stat.S_IFCHR: "character",
    stat.S_IFDIR: "directory",
    stat.S_IFIFO: "fifo",
    stat.S_IFLNK: "symlink",
    stat.S_IFREG: "regular",
    stat.S_IFSOCK: "socket",
    0160000: "whiteout",
}


class FD(object):
    def __init__(self, fd, stat_result=None, pid=None):
        self.fd = fd
        if stat_result is None:
            if pid is None or pid == os.getpid():
                stat_result = os.fstat(fd)
            else:
                stat_result = stat_pid_fd(pid, fd)

        self._stat_result = stat_result

    @property
    def mode(self):
        return self._stat_result.st_mode
    
    @property
    def typestr(self):
        return _TYPE_LOOKUP.get(stat.S_IFMT(self.mode),
                                "unknown (0%o)" % stat.S_IFMT(self.mode))

    def __int__(self):
        return self.fd

    def __repr__(self):
        return "<%s file (%d)>" % (self.typestr, self.fd)



if __name__ == '__main__':
    import errno
    import argparse
    ap = argparse.ArgumentParser()
    ap.add_argument("pids", nargs="*", default=[None], type=int, metavar="PID")
    ns = ap.parse_args()
    for pid in ns.pids:
        for fd in get_open_fds(pid):
            try:
                print FD(fd, pid=pid)
            except OSError as e:
                if e.errno == errno.EBADF:
                    print "%d: EBADF" % fd

@@ -459,19 +459,91 @@
 ass 
-FD(object):
+_FileDescriptor(object):%0A    %22%22%22Base class for local and remote file descriptors%22%22%22
 %0A   
@@ -581,23 +581,13 @@
 sult
-=None, pid=None
+, pid
 ):%0A 
@@ -618,194 +618,22 @@
     
-if stat_result is None:%0A            if pid is None or pid == os.getpid():%0A                stat_result = os.fstat(fd)%0A            else:%0A                stat_result = stat_pid_fd(pid, fd)%0A
+self.pid = pid
 %0A   
@@ -1013,23 +1013,37 @@
 %3C%25s 
+%25s 
 file 
-(
+#
 %25d
-)
 %3E%22 %25 (
+self.LOCAL, 
 self
@@ -1063,16 +1063,745 @@
 f.fd)%0A%0A%0A
+class LocalFileDescriptor(_FileDescriptor):%0A    %22%22%22A file descriptor belonging to the current process%22%22%22%0A    LOCAL = %22local%22%0A%0A%0Aclass RemoteFileDescriptor(_FileDescriptor):%0A    %22%22%22A file descriptor belonging to another process%22%22%22%0A    LOCAL = %22remote%22%0A%0A%0Adef FD(fd, stat_result=None, pid=None):%0A    if pid is None:%0A        pid = os.getpid()%0A        local = True%0A    elif pid == os.getpid():%0A        local = True%0A    else:%0A        local = False%0A%0A    if stat_result is None:%0A        if local:%0A            stat_result = os.fstat(fd)%0A        else:%0A            stat_result = stat_pid_fd(pid, fd)%0A%0A    if local:%0A        return LocalFileDescriptor(fd, stat_result, pid)%0A    else:%0A        return RemoteFileDescriptor(fd, stat_result, pid)%0A%0A
 %0Aif __na

Split "FD" class up