PageRenderTime 57ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/fstmerge/examples/SpamBayes/rev3250-3267/spambayes/spambayes/Version.py

https://github.com/RoDaniel/featurehouse
Python | 519 lines | 484 code | 33 blank | 2 comment | 7 complexity | a6dcf9a6162e34f94cca912ee4f2f41b MD5 | raw file
  1. """Simple version repository for SpamBayes core, and our main apps.
  2. Also has the ability to load this version information from a remote location
  3. (in that case, we actually load a "ConfigParser" version of the file to
  4. avoid importing code we can't trust.) This allows any app to check if there
  5. is a later version available.
  6. The makefile process for the website will execute this as a script, which
  7. will generate the "ConfigParser" version for the web.
  8. """
  9. import sys
  10. import re
  11. try:
  12. _
  13. except NameError:
  14. _ = lambda arg: arg
  15. LATEST_VERSION_HOME = "http://spambayes.sourceforge.net/download/Version.cfg"
  16. DEFAULT_DOWNLOAD_PAGE = "http://spambayes.sourceforge.net/windows.html"
  17. versions = {
  18. "Download Page": DEFAULT_DOWNLOAD_PAGE,
  19. "Apps": {
  20. "Outlook" : {
  21. "Description": "SpamBayes Outlook Addin",
  22. },
  23. "POP3 Proxy" : {
  24. "Description": "SpamBayes POP3 Proxy",
  25. },
  26. },
  27. }
  28. def get_version(app = None,
  29. version_dict = None):
  30. """Get SBVersion object based on the version info in the supplied dict."""
  31. ver = SBVersion()
  32. if version_dict is not None:
  33. dict = version_dict
  34. if app is not None:
  35. try:
  36. dict = version_dict["Apps"][app]
  37. except KeyError:
  38. pass
  39. try:
  40. version = dict["Version"]
  41. try:
  42. float(version)
  43. dot = version.find('.')
  44. ver_frac_part = version[dot+1:]
  45. if len(ver_frac_part) > 1:
  46. version = version[0:dot] + '.' + ver_frac_part[0] + '.' + ver_frac_part[1:]
  47. except ValueError:
  48. pass
  49. ver = SBVersion(version, version_dict["Date"])
  50. except KeyError:
  51. pass
  52. return ver
  53. def get_download_page(app = None,
  54. version_dict = None):
  55. if version_dict is None:
  56. version_dict = versions
  57. dict = version_dict
  58. if app is not None:
  59. try:
  60. dict = version_dict["Apps"][app]
  61. except KeyError:
  62. pass
  63. try:
  64. return dict["Download Page"]
  65. except KeyError:
  66. return DEFAULT_DOWNLOAD_PAGE
  67. def get_current_version():
  68. return SBVersion()
  69. class SBVersion :
  70. """Version numbering for SpamBayes releases.
  71. A version number consists of two or three dot-separated numeric
  72. components, with an optional "pre-release" tag on the end. The
  73. pre-release tag consists of the designations 'a' (for alpha),
  74. 'b' (for beta), or 'rc' (for release candidate) followed by a number.
  75. If the numeric components of two version numbers are equal, then one
  76. with a pre-release tag will always be deemed earlier (lesser) than
  77. one without.
  78. The following are valid version numbers (shown in the order that
  79. would be obtained by sorting according to the supplied cmp function):
  80. 0.4 0.4.0 (these two are equivalent)
  81. 0.4.1
  82. 0.5a1
  83. 0.5b3
  84. 0.5
  85. 0.9.6
  86. 1.0
  87. 1.0.4a3
  88. 1.0.4b1
  89. 1.0.4rc2
  90. 1.0.4
  91. The following are examples of invalid version numbers:
  92. 1
  93. 2.7.2.2
  94. 1.3.a4
  95. 1.3pl1
  96. 1.3c4
  97. A date may also be associated with the version, typically to track the
  98. date when the release was made public. The date is specified as a string,
  99. and is only used in formatting the long version of the version string.
  100. """
  101. def __init__(self, vstring=None, date=None):
  102. import spambayes
  103. if vstring:
  104. self.parse(vstring)
  105. else:
  106. self.parse(spambayes.__version__)
  107. if date:
  108. self.date = date
  109. else:
  110. self.date = spambayes.__date__
  111. def __repr__ (self):
  112. return "%s('%s', '%s')" % (self.__class__.__name__, str(self), self.date)
  113. version_re = re.compile(r'^(\d+) \. (\d+) (\. (\d+))? (([ab]|rc)(\d+))?\+?$',
  114. re.VERBOSE)
  115. def parse(self, vstring):
  116. match = self.version_re.match(vstring)
  117. if not match:
  118. raise ValueError("invalid version number '%s'" % vstring)
  119. (major, minor, patch, prerelease, prerelease_num) = \
  120. match.group(1, 2, 4, 6, 7)
  121. if not patch:
  122. patch = "0"
  123. if not prerelease:
  124. releaselevel = "final"
  125. serial = 0
  126. else:
  127. serial = int(prerelease_num)
  128. if prerelease == "a":
  129. releaselevel = "alpha"
  130. elif prerelease == "b":
  131. releaselevel = "beta"
  132. elif prerelease == "rc":
  133. releaselevel = "candidate"
  134. self.version_info = tuple(list(map(int, [major, minor, patch])) + \
  135. [releaselevel, serial])
  136. def __str__(self):
  137. if self.version_info[2] == 0:
  138. vstring = '.'.join(map(str, self.version_info[0:2]))
  139. else:
  140. vstring = '.'.join(map(str, self.version_info[0:3]))
  141. releaselevel = self.version_info[3][0]
  142. if releaselevel != 'f':
  143. if releaselevel == 'a':
  144. prerelease = "a"
  145. elif releaselevel == 'b':
  146. prerelease = "b"
  147. elif releaselevel == 'c':
  148. prerelease = "rc"
  149. vstring = vstring + prerelease + str(self.version_info[4])
  150. return vstring
  151. def __cmp__(self, other):
  152. if isinstance(other, str):
  153. other = SBVersion(other)
  154. return cmp(self.version_info, other.version_info)
  155. def get_long_version(self, app_name = None):
  156. if app_name is None:
  157. app_name = "SpamBayes"
  158. return _("%s Version %s (%s)") % (app_name, str(self), self.date)
  159. try:
  160. import configparser
  161. class MySafeConfigParser(configparser.SafeConfigParser):
  162. def optionxform(self, optionstr):
  163. return optionstr
  164. except AttributeError:
  165. MySafeConfigParser = None
  166. def fetch_latest_dict(url=LATEST_VERSION_HOME):
  167. if MySafeConfigParser is None:
  168. raise RuntimeError("Sorry, but only Python 2.3+ can trust remote config files")
  169. import urllib.request, urllib.error, urllib.parse
  170. from spambayes.Options import options
  171. server = options["globals", "proxy_server"]
  172. if server != "":
  173. if ':' in server:
  174. server, port = server.split(':', 1)
  175. port = int(port)
  176. else:
  177. port = 8080
  178. if options["globals", "proxy_username"]:
  179. user_pass_string = "%s:%s" % \
  180. (options["globals", "proxy_username"],
  181. options["globals", "proxy_password"])
  182. else:
  183. user_pass_string = ""
  184. proxy_support = urllib.request.ProxyHandler({"http" :
  185. "http://%s@%s:%d" % \
  186. (user_pass_string, server,
  187. port)})
  188. opener = urllib.request.build_opener(proxy_support, urllib2.HTTPHandler)
  189. urllib.request.install_opener(opener)
  190. stream = urllib.request.urlopen(url)
  191. cfg = MySafeConfigParser()
  192. cfg.readfp(stream)
  193. ret_dict = {}
  194. apps_dict = ret_dict["Apps"] = {}
  195. for sect in cfg.sections():
  196. if sect == "SpamBayes":
  197. target_dict = ret_dict
  198. else:
  199. target_dict = apps_dict.setdefault(sect, {})
  200. for opt in cfg.options(sect):
  201. val = cfg.get(sect, opt)
  202. target_dict[opt] = val
  203. return ret_dict
  204. try:
  205. import ConfigParser
  206. class MySafeConfigParser(ConfigParser.SafeConfigParser):
  207. def optionxform(self, optionstr):
  208. return optionstr
  209. except AttributeError:
  210. MySafeConfigParser = None
  211. compat_apps = {
  212. "Outlook" : {
  213. "Description": "SpamBayes Outlook Addin",
  214. },
  215. "POP3 Proxy" : {
  216. "Description": "SpamBayes POP3 Proxy",
  217. },
  218. }
  219. shared_cfg_opts = {
  220. "Download Page": "http://spambayes.sourceforge.net/windows.html",
  221. }
  222. def _write_cfg_opts(stream, this_dict):
  223. for name, val in list(this_dict.items()):
  224. if type(val)==type(''):
  225. val_str = repr(val)[1:-1]
  226. elif type(val)==type(0.0):
  227. val_str = str(val)
  228. elif type(val)==type({}):
  229. val_str = None
  230. else:
  231. print("Skipping unknown value type: %r" % val)
  232. val_str = None
  233. if val_str is not None:
  234. stream.write("%s:%s\n" % (name, val_str))
  235. def _make_compatible_cfg_section(stream, key, ver, this_dict):
  236. stream.write("[%s]\n" % key)
  237. ver_num = float(ver.version_info[0])
  238. ver_num += float(ver.version_info[1] * 0.1)
  239. ver_num += float(ver.version_info[2] * 0.01)
  240. releaselevel = ver.version_info[3][0]
  241. if releaselevel == 'a':
  242. prerelease_offset = 0.001 - (float(ver.version_info[4]) * 0.00001)
  243. elif releaselevel == 'b':
  244. prerelease_offset = 0.0005 - (float(ver.version_info[4]) * 0.00001)
  245. elif releaselevel == 'c':
  246. prerelease_offset = 0.0001 - (float(ver.version_info[4]) * 0.00001)
  247. else:
  248. prerelease_offset = 0.0
  249. ver_num -= prerelease_offset
  250. stream.write("Version:%s\n" % str(ver_num))
  251. stream.write("BinaryVersion:%s\n" % str(ver_num))
  252. stream.write("Date:%s\n" % ver.date)
  253. _write_cfg_opts(stream, this_dict)
  254. desc_str = "%%(Description)s Version %s (%%(Date)s)" % str(ver)
  255. stream.write("Full Description:%s\n" % desc_str)
  256. stream.write("Full Description Binary:%s\n" % desc_str)
  257. _write_cfg_opts(stream, versions)
  258. stream.write("\n")
  259. def _make_cfg_section(stream, ver):
  260. stream.write("[SpamBayes]\n")
  261. stream.write("Version:%s\n" % str(ver))
  262. stream.write("Date:%s\n" % ver.date)
  263. _write_cfg_opts(stream, versions)
  264. stream.write("\n")
  265. def make_cfg(stream):
  266. stream.write("# This file is generated from spambayes/Version.py" \
  267. " - do not edit\n")
  268. ver = get_current_version()
  269. _make_cfg_section(stream, ver)
  270. for appname in compat_apps:
  271. _make_compatible_cfg_section(stream, appname, ver, versions["Apps"][appname])
  272. def main(args):
  273. if '-g' in args:
  274. make_cfg(sys.stdout)
  275. sys.exit(0)
  276. v_this = get_current_version()
  277. print("Current version:", v_this.get_long_version())
  278. print()
  279. print("Fetching the lastest version information...")
  280. try:
  281. latest_dict = fetch_latest_dict()
  282. except:
  283. print("FAILED to fetch the latest version")
  284. import traceback
  285. traceback.print_exc()
  286. sys.exit(1)
  287. v_latest = get_version(version_dict=latest_dict)
  288. print()
  289. print("Latest version:", v_latest.get_long_version())
  290. if __name__ == '__main__':
  291. main(sys.argv)
  292. if __name__ == '__main__':
  293. main(sys.argv)
  294. try:
  295. _
  296. except NameError:
  297. _ = lambda arg: arg