utils.py 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. #!/usr/bin/env python
  2. # -*- coding = utf-8 -*-
  3. # filename: utils.py
  4. import os, sys, stat
  5. import ConfigParser
  6. import StringIO
  7. SUFFIX = ['B', 'KB', 'MB', 'GB','TB', 'PB', 'EB', 'ZB', 'YB']
  8. def appromix(size, base = 0):
  9. '''Conver bytes stream size to human-readable format.
  10. Keyword arguments:
  11. size: int, bytes stream size
  12. base: int, suffix index
  13. Return: string
  14. '''
  15. multiples = 1024
  16. if size < 0:
  17. raise ValueError('[-] Error: number must be non-negative.')
  18. if size < multiples:
  19. return '{0:d}{1}'.format(size, SUFFIX[base])
  20. for suffix in SUFFIX[base:]:
  21. if size < multiples:
  22. return '{0:.2f}{1}'.format(size,suffix)
  23. size //=multiples
  24. raise ValueError('[-] Error: number too big.')
  25. def get_file_ext_name(filename, double_ext = True):
  26. li = filename.split(os.extsep)
  27. if len(li) <= 1:
  28. return ''
  29. else:
  30. if li[-1].find(os.sep) != -1:
  31. return ''
  32. if double_ext:
  33. if len(li) > 2:
  34. if li[-2].find(os.sep) == -1:
  35. return '%s.%s' % (li[-2], li[-1])
  36. return li[-1]
  37. class Fdfs_ConfigParser(ConfigParser.RawConfigParser):
  38. """
  39. Extends ConfigParser to allow files without sections.
  40. This is done by wrapping read files and prepending them with a placeholder
  41. section, which defaults to '__config__'
  42. """
  43. def __init__(self, default_section=None, *args, **kwargs):
  44. ConfigParser.RawConfigParser.__init__(self, *args, **kwargs)
  45. self._default_section = None
  46. self.set_default_section(default_section or '__config__')
  47. def get_default_section(self):
  48. return self._default_section
  49. def set_default_section(self, section):
  50. self.add_section(section)
  51. # move all values from the previous default section to the new one
  52. try:
  53. default_section_items = self.items(self._default_section)
  54. self.remove_section(self._default_section)
  55. except ConfigParser.NoSectionError:
  56. pass
  57. else:
  58. for (key, value) in default_section_items:
  59. self.set(section, key, value)
  60. self._default_section = section
  61. def read(self, filenames):
  62. if isinstance(filenames, basestring):
  63. filenames = [filenames]
  64. read_ok = []
  65. for filename in filenames:
  66. try:
  67. with open(filename) as fp:
  68. self.readfp(fp)
  69. except IOError:
  70. continue
  71. else:
  72. read_ok.append(filename)
  73. return read_ok
  74. def readfp(self, fp, *args, **kwargs):
  75. stream = StringIO.StringIO()
  76. try:
  77. stream.name = fp.name
  78. except AttributeError:
  79. pass
  80. stream.write('[' + self._default_section + ']\n')
  81. stream.write(fp.read())
  82. stream.seek(0, 0)
  83. return self._read(stream, stream.name)
  84. def write(self, fp):
  85. # Write the items from the default section manually and then remove them
  86. # from the data. They'll be re-added later.
  87. try:
  88. default_section_items = self.items(self._default_section)
  89. self.remove_section(self._default_section)
  90. for (key, value) in default_section_items:
  91. fp.write("{0} = {1}\n".format(key, value))
  92. fp.write("\n")
  93. except ConfigParser.NoSectionError:
  94. pass
  95. ConfigParser.RawConfigParser.write(self, fp)
  96. self.add_section(self._default_section)
  97. for (key, value) in default_section_items:
  98. self.set(self._default_section, key, value)
  99. def _read(self, fp, fpname):
  100. """Parse a sectioned setup file.
  101. The sections in setup file contains a title line at the top,
  102. indicated by a name in square brackets (`[]'), plus key/value
  103. options lines, indicated by `name: value' format lines.
  104. Continuations are represented by an embedded newline then
  105. leading whitespace. Blank lines, lines beginning with a '#',
  106. and just about everything else are ignored.
  107. """
  108. cursect = None # None, or a dictionary
  109. optname = None
  110. lineno = 0
  111. e = None # None, or an exception
  112. while True:
  113. line = fp.readline()
  114. if not line:
  115. break
  116. lineno = lineno + 1
  117. # comment or blank line?
  118. if line.strip() == '' or line[0] in '#;':
  119. continue
  120. if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR":
  121. # no leading whitespace
  122. continue
  123. # continuation line?
  124. if line[0].isspace() and cursect is not None and optname:
  125. value = line.strip()
  126. if value:
  127. cursect[optname] = "%s\n%s" % (cursect[optname], value)
  128. # a section header or option header?
  129. else:
  130. # is it a section header?
  131. mo = self.SECTCRE.match(line)
  132. if mo:
  133. sectname = mo.group('header')
  134. if sectname in self._sections:
  135. cursect = self._sections[sectname]
  136. elif sectname == DEFAULTSECT:
  137. cursect = self._defaults
  138. else:
  139. cursect = self._dict()
  140. cursect['__name__'] = sectname
  141. self._sections[sectname] = cursect
  142. # So sections can't start with a continuation line
  143. optname = None
  144. # no section header in the file?
  145. elif cursect is None:
  146. raise MissingSectionHeaderError(fpname, lineno, line)
  147. # an option line?
  148. else:
  149. mo = self.OPTCRE.match(line)
  150. if mo:
  151. optname, vi, optval = mo.group('option', 'vi', 'value')
  152. if vi in ('=', ':') and ';' in optval:
  153. # ';' is a comment delimiter only if it follows
  154. # a spacing character
  155. pos = optval.find(';')
  156. if pos != -1 and optval[pos-1].isspace():
  157. optval = optval[:pos]
  158. optval = optval.strip()
  159. # allow empty values
  160. if optval == '""':
  161. optval = ''
  162. optname = self.optionxform(optname.rstrip())
  163. if cursect.has_key(optname):
  164. if not isinstance(cursect[optname], list):
  165. cursect[optname] = [cursect[optname]]
  166. cursect[optname].append(optval)
  167. else:
  168. cursect[optname] = optval
  169. else:
  170. # a non-fatal parsing error occurred. set up the
  171. # exception but keep going. the exception will be
  172. # raised at the end of the file and will contain a
  173. # list of all bogus lines
  174. if not e:
  175. e = ParsingError(fpname)
  176. e.append(lineno, repr(line))
  177. # if any parsing errors occurred, raise an exception
  178. if e:
  179. raise e
  180. def split_remote_fileid(remote_file_id):
  181. '''
  182. Splite remote_file_id to (group_name, remote_file_name)
  183. arguments:
  184. @remote_file_id: string
  185. @return tuple, (group_name, remote_file_name)
  186. '''
  187. index = remote_file_id.find('/')
  188. if -1 == index:
  189. return None
  190. return (remote_file_id[0:index], remote_file_id[(index + 1):])
  191. def fdfs_check_file(filename):
  192. ret = True
  193. errmsg = ''
  194. if not os.path.isfile(filename):
  195. ret = False
  196. errmsg = '[-] Error: %s is not a file.' % filename
  197. elif not stat.S_ISREG(os.stat(filename).st_mode):
  198. ret = False
  199. errmsg = '[-] Error: %s is not a regular file.' % filename
  200. return (ret, errmsg)
  201. if __name__ == '__main__':
  202. print get_file_ext_name('/bc.tar.gz')