HWRF  trunk@4391
listing.py
1 """!Contains the Listing class, which emulates "ls -l"."""
2 
3 ##@var __all__
4 # Symbols exported by "from produtil.listing import *"
5 __all__=['Listing']
6 
7 import os,stat,StringIO,grp,pwd,time
8 
9 class Listing(object):
10  """!Imitates the shell "ls -l" program.
11 
12  Imitate ls -l, but with a longer mtime string:
13  @code
14  print Listing("/usr/local")
15  @endcode
16 
17  To include files whose names begin with "." add hidden=True:
18  @code
19  print Listing("/usr/local",hidden=True)
20  @endcode
21 
22  To log messages related to failures of lstat and readlink, pass
23  a logging.Logger:
24  @code
25  print Listing("/usr/local",hidden=True,logger=logger)
26  @endcode"""
27  def __init__(self,path=".",hidden=False,logger=None):
28  """!Constructor for Listing:
29  @param path The directory path to list.
30  @param hidden If True, files with names beginning with "." are listed.
31  @param logger A logging.Logger for error messages."""
32  self.__path=path
33  self.__contents=dict()
34  self.list(hidden=bool(hidden),logger=logger)
35  def __iter__(self):
36  """!Iterates over filenames in the listed directory."""
37  for name in self.contents.iterkeys():
38  yield name
39  def iteritems(self):
40  """!Iterates over name,data pairs in the listed directory. The
41  "data" will be a tuple containing the output of lstat and the
42  output of readlink."""
43  for (name,data) in self.contents.iteritems():
44  yield name,data
45  def iterkeys(self):
46  """!Iterates over filenames in the listed directory."""
47  for name in self.contents.iterkeys():
48  yield name
49 
50  def list(self,hidden=False,logger=None):
51  """!Updates the internal data structures with a new listing of
52  the directory. Arguments are the same as for the constructor.
53  @param hidden If True, files with names beginning with "." are listed.
54  @param logger A logging.Logger for error messages."""
55  hidden=bool(hidden)
56  path=self.__path
57  listing=os.listdir(path)
58  contents=dict()
59  for item in listing:
60  if item[0]=='.' and not hidden:
61  # Skip "hidden" files.
62  continue
63  loc=os.path.join(path,item)
64  try:
65  lstat=os.lstat(loc)
66  except EnvironmentError as e:
67  if logger is not None:
68  logger.info(
69  "%s: cannot lstat: %s"%(loc,str(e)),exc_info=True)
70  continue
71  if not stat.S_ISLNK(lstat.st_mode):
72  contents[item]=(lstat,None)
73  continue
74  try:
75  linkpath=os.readlink(loc)
76  except EnvironmentError as e:
77  if logger is not None:
78  logger.info(
79  "%s: cannot readlink: %s"%(loc,str(e)),exc_info=True)
80  contents[item]=(lstat,"(**UNKNOWN**)")
81  continue
82  contents[item]=(lstat,linkpath)
83  self.__contents=contents
84  def __str__(self):
85  """!Generates an ls -l style listing of the directory."""
86  c=self.__contents
87  sizes=[0,0,0,0,0,0]
88  rows=list()
89  for (name,item) in c.iteritems():
90  row=self._stritem(name,item)
91  for col in xrange(len(row)-1):
92  sizes[col]=max(sizes[col],len(row[col]))
93  rows.append(row)
94  format=' %%%ds'*6+' %%s\n'
95  format=format[1:]
96  format=format%tuple(sizes)
97 
98  s=StringIO.StringIO()
99  for row in rows:
100  s.write(format%row)
101  st=s.getvalue()
102  s.close()
103  return st
104  def _stritem(self,name,item):
105  """!This is an internal implementation function. Do not call
106  it directly. It generates one line of ls output as a tuple of
107  strings, one string per column of information (the mtime is
108  one column). The __str__ turns the lines into one big string.
109  @param name the filename
110  @param item details about the file
111  @returns data for each column of the listing"""
112  lstat=item[0]
113  linkpath=item[1]
114  if linkpath is None: linkpath='(**UNKNOWN**)'
115  mode=lstat.st_mode
116 
117  s=''
118 
119  # file type character
120  if stat.S_ISDIR(mode): s+='d'
121  elif stat.S_ISCHR(mode): s+='c'
122  elif stat.S_ISBLK(mode): s+='b'
123  elif stat.S_ISFIFO(mode): s+='p'
124  elif stat.S_ISLNK(mode): s+='l'
125  elif stat.S_ISSOCK(mode): s+='s'
126  else: s+='-'
127 
128  # User permissions
129  s+=('r' if mode&stat.S_IRUSR else '-')
130  s+=('w' if mode&stat.S_IWUSR else '-')
131  if mode&stat.S_IXUSR:
132  if mode&stat.S_ISUID:
133  s+='s'
134  else:
135  s+='x'
136  elif mode&stat.S_ISUID:
137  s+='S'
138  else:
139  s+='-'
140 
141  # Group permissions
142  s+=('r' if mode&stat.S_IRGRP else '-')
143  s+=('w' if mode&stat.S_IWGRP else '-')
144  if mode&stat.S_IXGRP:
145  if mode&stat.S_ISGID:
146  s+='s'
147  else:
148  s+='x'
149  elif mode&stat.S_ISGID:
150  s+='S'
151  else:
152  s+='-'
153 
154 
155  # Other permissions
156  s+=('r' if mode&stat.S_IROTH else '-')
157  s+=('w' if mode&stat.S_IWOTH else '-')
158  if mode&stat.S_IXOTH:
159  if mode&stat.S_ISVTX:
160  s+='t'
161  else:
162  s+='x'
163  elif mode&stat.S_ISVTX:
164  s+='T'
165  else:
166  s+='-'
167 
168  nlink=str(int(lstat.st_nlink))
169  username=self._username(lstat.st_uid)
170  groupname=self._groupname(lstat.st_gid)
171  size=str(int(lstat.st_size))
172  when=time.asctime(time.localtime(lstat.st_mtime))
173  if stat.S_ISLNK(lstat.st_mode):
174  return (s,nlink,username,groupname,size,when,name+' -> '+linkpath)
175  else:
176  return (s,nlink,username,groupname,size,when,name)
177 
178 
179  def _groupname(self,gid):
180  """!Return the group name for a group ID from getgrgid."""
181  try:
182  gr=grp.getgrgid(gid)
183  return str(gr.gr_name)
184  except (KeyError,ValueError,EnvironmentError):
185  return str(gid)
186 
187  def _username(self,uid):
188  """!Return the user name for a group ID from getpwuid."""
189  try:
190  pw=pwd.getpwuid(uid)
191  return str(pw.pw_name)
192  except (KeyError,ValueError,EnvironmentError):
193  return str(uid)
Imitates the shell "ls -l" program.
Definition: listing.py:9
def __init__
Constructor for Listing:
Definition: listing.py:27
def _username(self, uid)
Return the user name for a group ID from getpwuid.
Definition: listing.py:187
def iteritems(self)
Iterates over name,data pairs in the listed directory.
Definition: listing.py:39
def __iter__(self)
Iterates over filenames in the listed directory.
Definition: listing.py:35
def list
Updates the internal data structures with a new listing of the directory.
Definition: listing.py:50
def iterkeys(self)
Iterates over filenames in the listed directory.
Definition: listing.py:45
def _groupname(self, gid)
Return the group name for a group ID from getgrgid.
Definition: listing.py:179
def _stritem(self, name, item)
This is an internal implementation function.
Definition: listing.py:104
def __str__(self)
Generates an ls -l style listing of the directory.
Definition: listing.py:84