Am 13.05.2013 00:04, schrieb Ben Hoyt: > In fact, I don't think .cached_lstat should be exposed to the user. > They just call entry.lstat(), and it returns a cached stat or calls > os.lstat() to get the real stat if required (and populates the > internal cached stat value). And the entry.is* functions would call > entry.lstat() if dirent was or d_type was DT_UNKNOWN. This would > change relatively nasty code like this:
I would prefer to go the other route and don't expose lstat(). It's cleaner and less confusing to have a property cached_lstat on the object because it actually says what it contains. The property's internal code can do a lstat() call if necessary. Your code example doesn't handle the case of a failing lstat() call. It can happen when the file is removed or permission of a parent directory changes. > This change would make scandir() usable by ordinary mortals, rather > than just hardcore library implementors. Why not have both? The os module exposes and leaks the platform details on more than on occasion. A low level function can expose name + dirent struct on POSIX and name + stat_result on Windows. Then you can build a high level API like os.scandir() in pure Python code. > class DirEntry: > def __init__(self, name, dirent, lstat, path='.'): > # User shouldn't need to call this, but called internally by scandir() > self.name = name > self.dirent = dirent > self._lstat = lstat # non-public attributes > self._path = path You should include the fd of the DIR pointer here for the new *at() function family. > def lstat(self): > if self._lstat is None: > self._lstat = os.lstat(os.path.join(self._path, self.name)) > return self._lstat The function should use fstatat(2) function (os.lstat with dir_fd) when it is available on the current platform. It's better and more secure than lstat() with a joined path. > def isdir(self): > if self.dirent is not None and self.dirent.d_type != DT_UNKNOWN: > return self.dirent.d_type == DT_DIR > else: > return stat.S_ISDIR(self.lstat().st_mode) > > def isfile(self): > if self.dirent is not None and self.dirent.d_type != DT_UNKNOWN: > return self.dirent.d_type == DT_REG > else: > return stat.S_ISREG(self.lstat().st_mode) > > def islink(self): > if self.dirent is not None and self.dirent.d_type != DT_UNKNOWN: > return self.dirent.d_type == DT_LNK > else: > return stat.S_ISLNK(self.lstat().st_mode) A bit faster: d_type = getattr(self.dirent, "d_type", DT_UNKNOWN) if d_type != DT_UNKNOWN: return d_type == DT_LNK The code doesn't handle a failing lstat() call. Christian _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com