PageRenderTime 45ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/R/tests/build_minicran.py

https://github.com/dbfree/h2o
Python | 434 lines | 415 code | 13 blank | 6 comment | 11 complexity | 194cda7abf52776928016abab6f5e2ef MD5 | raw file
Possible License(s): Apache-2.0
  1. #!/usr/bin/python
  2. import os
  3. import sys
  4. import urllib2
  5. import tempfile
  6. import atexit
  7. import shutil
  8. import re
  9. def download_file(url, download_path):
  10. print "URL: " + url
  11. u = urllib2.urlopen(url)
  12. f = open(download_path, 'wb')
  13. meta = u.info()
  14. file_size = int(meta.getheaders("Content-Length")[0])
  15. print "Downloading: %s (%s bytes)" % (download_path, file_size)
  16. file_size_dl = 0
  17. block_sz = 8192
  18. while True:
  19. buf = u.read(block_sz)
  20. if not buf:
  21. break
  22. file_size_dl += len(buf)
  23. f.write(buf)
  24. # status = r"%10d [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
  25. # status = status + chr(8)*(len(status)+1)
  26. # print status,
  27. f.close()
  28. print "Download complete."
  29. class CranPackage:
  30. def __init__(self, package_name):
  31. self.package_name = package_name
  32. self.package_dependencies = []
  33. self.package_version = None
  34. def set_version(self, package_version):
  35. self.package_version = package_version
  36. def add_dependencies(self, dependencies):
  37. stripped = dependencies.strip()
  38. arr = stripped.split(',')
  39. for dep in arr:
  40. stripped_dep = dep.strip()
  41. if (len(stripped_dep) == 0):
  42. continue
  43. m = re.match(r'\(.*', stripped_dep)
  44. if (m is not None):
  45. continue
  46. m = re.match(r'([a-zA-Z0-9\.]*)[ (]?.*', stripped_dep)
  47. if (m is None):
  48. print("")
  49. print("ERROR: Match failed for " + self.package_name + " (" + stripped_dep + ")")
  50. print("")
  51. sys.exit(1)
  52. dependency_name = m.group(1)
  53. self.package_dependencies.append(dependency_name)
  54. def get_name(self):
  55. return self.package_name
  56. def get_version(self):
  57. return self.package_version
  58. def emit(self):
  59. print("PACKAGE: " + self.package_name)
  60. for dep in self.package_dependencies:
  61. print(" " + dep)
  62. class CranDirectory:
  63. def __init__(self, packages_file):
  64. self.packages_file = packages_file
  65. self.packages_map = {}
  66. self._parse()
  67. def has_package(self, package_name):
  68. if (package_name not in self.packages_map):
  69. return False
  70. return True
  71. def get_dependencies_for_package(self, package_name):
  72. if (not self.has_package(package_name)):
  73. raise Exception
  74. p = self.packages_map[package_name]
  75. return p.package_dependencies
  76. def get_package(self, package_name):
  77. if (not self.has_package(package_name)):
  78. raise Exception
  79. p = self.packages_map[package_name]
  80. return p
  81. def emit(self):
  82. package_names = self.packages_map.keys()
  83. for package_name in package_names:
  84. p = self.get_package(package_name)
  85. p.emit()
  86. def _parse(self):
  87. f = open(self.packages_file, "r")
  88. STATE_NONE = 1
  89. STATE_IN_DEP = 2
  90. state = STATE_NONE
  91. p = None
  92. for line in f:
  93. if (len(line) == 0):
  94. f.close()
  95. return
  96. line = line.rstrip('\r\n')
  97. m = re.match(r'Package: (\S+)', line)
  98. if (m is not None):
  99. package_name = m.group(1)
  100. p = CranPackage(package_name)
  101. self._add_package(p)
  102. state = STATE_NONE
  103. continue
  104. m = re.match(r'Version: (\S+)', line)
  105. if (m is not None):
  106. package_version = m.group(1)
  107. p.set_version(package_version)
  108. state = STATE_NONE
  109. continue
  110. m = re.match(r'Depends: (.*)', line)
  111. if (m is not None):
  112. s = m.group(1)
  113. p.add_dependencies(s)
  114. state = STATE_IN_DEP
  115. continue
  116. if (':' in line):
  117. state = STATE_NONE
  118. continue
  119. if (state == STATE_IN_DEP):
  120. if (p is not None):
  121. p.add_dependencies(line)
  122. f.close()
  123. def _add_package(self, package):
  124. self.packages_map[package.get_name()] = package
  125. class MinicranBuilder:
  126. def __init__(self, print_only, output_dir, tmp_dir, platform, rversion, branch, buildnum):
  127. self.print_only = print_only
  128. self.output_dir = output_dir
  129. self.tmp_dir = tmp_dir
  130. self.platform = platform
  131. self.rversion = rversion
  132. self.branch = branch
  133. self.buildnum = buildnum
  134. self.s3_url_prefix = "https://h2o-release.s3.amazonaws.com/h2o/"
  135. self.repo_subdir = None
  136. self.extension = None
  137. self.project_version = None
  138. self.h2o_cran = None
  139. self.full_cran = None
  140. def create_output_dir(self):
  141. if (os.path.exists(self.output_dir)):
  142. print("")
  143. print("ERROR: Output directory already exists: " + self.output_dir)
  144. print("")
  145. sys.exit(1)
  146. try:
  147. os.makedirs(self.output_dir)
  148. except OSError as e:
  149. print("")
  150. print("mkdir failed (errno {0}): {1}".format(e.errno, e.strerror))
  151. print(" " + self.output_dir)
  152. print("")
  153. sys.exit(1)
  154. def create_cran_layout(self):
  155. if (self.platform == "windows"):
  156. self.repo_subdir = "bin/" + self.platform + "/contrib/" + self.rversion
  157. self.extension = ".zip"
  158. elif (self.platform == "macosx"):
  159. self.repo_subdir = "bin/" + self.platform + "/contrib/" + self.rversion
  160. self.extension = ".tgz"
  161. else:
  162. self.repo_subdir = "src/contrib"
  163. self.extension = ".tar.gz"
  164. os.makedirs(os.path.join(self.output_dir, self.repo_subdir))
  165. def download_h2o(self):
  166. if (self.buildnum == "latest"):
  167. latest_url = self.s3_url_prefix + self.branch + "/latest"
  168. latest_path = os.path.join(self.tmp_dir, "latest")
  169. download_file(latest_url, latest_path)
  170. f = open(latest_path, "r")
  171. line = f.readline()
  172. self.buildnum = line.strip()
  173. f.close()
  174. print("H2O branch: " + self.branch)
  175. print("H2O build number: " + self.buildnum)
  176. project_version_url = self.s3_url_prefix + self.branch + "/" + str(self.buildnum) + "/project_version"
  177. project_version_path = os.path.join(self.tmp_dir, "project_version")
  178. download_file(project_version_url, project_version_path)
  179. if True:
  180. f = open(project_version_path, "r")
  181. line = f.readline()
  182. self.project_version = line.strip()
  183. f.close()
  184. print("H2O project version: " + self.project_version)
  185. # Need to unzip the jar file and unpack the R component.
  186. desc_file_name = "PACKAGES"
  187. desc_url = self.s3_url_prefix + self.branch + "/" + str(self.buildnum) + "/R/src/contrib/" + desc_file_name
  188. desc_path = os.path.join(self.tmp_dir, desc_file_name)
  189. download_file(desc_url, desc_path)
  190. self.h2o_cran = CranDirectory(desc_path)
  191. self.h2o_cran.emit()
  192. # r_source_file_name = "h2o_" + self.project_version + ".tar.gz"
  193. # r_source_url = self.s3_url_prefix + self.branch + "/" + str(self.buildnum) + "/R/src/contrib/" + r_source_file_name
  194. # r_source_path = os.path.join(self.tmp_dir, r_source_file_name)
  195. # download_file(r_source_url, r_source_path)
  196. # h2o_jar_file_name = "h2o-" + self.project_version + ".zip"
  197. # h2o_jar_url = self.s3_url_prefix + self.branch + "/" + str(self.buildnum) + "/" + h2o_jar_file_name
  198. # h2o_jar_path = os.path.join(self.tmp_dir, h2o_jar_file_name)
  199. # download_file(h2o_jar_url, h2o_jar_path)
  200. def extract_h2o_dependencies(self):
  201. pass
  202. def download_h2o_dependencies(self):
  203. pass
  204. def build(self):
  205. self.create_output_dir()
  206. self.create_cran_layout()
  207. self.download_h2o()
  208. self.extract_h2o_dependencies()
  209. self.download_h2o_dependencies()
  210. #--------------------------------------------------------------------
  211. # Main program
  212. #--------------------------------------------------------------------
  213. g_default_rversion = "3.0"
  214. g_default_branch = "master"
  215. g_default_buildnum = "latest"
  216. # Global variables that can be set by the user.
  217. g_script_name = ""
  218. g_platform = None
  219. g_output_dir = None
  220. g_tmp_dir = None
  221. g_rversion = g_default_rversion
  222. g_branch = g_default_branch
  223. g_buildnum = g_default_buildnum
  224. g_print_only = False
  225. def usage():
  226. print("")
  227. print("Build a minimal self-contained CRAN-line repo containing the H2O package")
  228. print("and its dependencies. The intent is that the output of this tool can be")
  229. print("put on a USB stick and installed on a computer with no network connection.")
  230. print("")
  231. print("Usage: " + g_script_name +
  232. " --platform <platform_name>"
  233. " --outputdir <dir>"
  234. " [--rversion <version_number>]"
  235. " [--branch <branch_name>]"
  236. " [--build <build_number>]"
  237. " [-n]")
  238. print("")
  239. print(" --platform OS that R runs on. (e.g. linux, windows, macosx)")
  240. print("")
  241. print(" --outputdir Directory to be created. It must not already exist.")
  242. print("")
  243. print(" --rversion Version of R. (e.g. 2.14, 2.15, 3.0)")
  244. print(" (Default is: "+g_default_rversion+")")
  245. print("")
  246. print(" --branch H2O git branch. (e.g. master, rel-jacobi)")
  247. print(" (Default is: "+g_default_branch+")")
  248. print("")
  249. print(" --buildnum H2O build number. (e.g. 1175, latest)")
  250. print(" (Default is: "+g_default_buildnum+")")
  251. print("")
  252. print(" -n Print what would be done, but don't actually do it.")
  253. print("")
  254. print("Examples:")
  255. print("")
  256. print(" Just accept the defaults and go:")
  257. print(" "+g_script_name)
  258. print("")
  259. print(" Build for R version 3.0.x on Windows; use the h2o jacobi release latest:")
  260. print(" "+g_script_name+" --platform windows --rversion 3.0 --branch rel-jacobi --build latest "
  261. "--outputdir h2o_minicran_windows_3.0_rel-jacobi")
  262. print("")
  263. sys.exit(1)
  264. def unknown_arg(s):
  265. print("")
  266. print("ERROR: Unknown argument: " + s)
  267. print("")
  268. usage()
  269. def bad_arg(s):
  270. print("")
  271. print("ERROR: Illegal use of (otherwise valid) argument: " + s)
  272. print("")
  273. usage()
  274. def unspecified_arg(s):
  275. print("")
  276. print("ERROR: Argument must be specified: " + s)
  277. print("")
  278. usage()
  279. def parse_args(argv):
  280. global g_platform
  281. global g_output_dir
  282. global g_rversion
  283. global g_branch
  284. global g_buildnum
  285. global g_print_only
  286. i = 1
  287. while (i < len(argv)):
  288. s = argv[i]
  289. if (s == "--platform"):
  290. i += 1
  291. if (i > len(argv)):
  292. usage()
  293. g_platform = argv[i]
  294. if (g_platform not in ["linux", "windows", "macosx"]):
  295. bad_arg(s)
  296. elif (s == "--rversion"):
  297. i += 1
  298. if (i > len(argv)):
  299. usage()
  300. g_rversion = argv[i]
  301. if (g_rversion not in ["2.14", "2.15", "3.0"]):
  302. bad_arg(s)
  303. elif (s == "--outputdir"):
  304. i += 1
  305. if (i > len(argv)):
  306. usage()
  307. g_output_dir = argv[i]
  308. elif (s == "--branch"):
  309. i += 1
  310. if (i > len(argv)):
  311. usage()
  312. g_branch = argv[i]
  313. elif (s == "--buildnum"):
  314. i += 1
  315. if (i > len(argv)):
  316. usage()
  317. g_buildnum = argv[i]
  318. elif (s == "-n"):
  319. g_print_only = True
  320. elif (s == "-h" or s == "--h" or s == "-help" or s == "--help"):
  321. usage()
  322. else:
  323. unknown_arg(s)
  324. i += 1
  325. if (g_platform is None):
  326. unspecified_arg("platform")
  327. if (g_output_dir is None):
  328. unspecified_arg("output directory")
  329. def remove_tmp_dir():
  330. if (os.path.exists(g_tmp_dir)):
  331. shutil.rmtree(g_tmp_dir)
  332. print "Removed tmp directory: " + g_tmp_dir
  333. def main(argv):
  334. """
  335. Main program.
  336. @return: none
  337. """
  338. global g_script_name
  339. global g_tmp_dir
  340. g_script_name = os.path.basename(argv[0])
  341. # Override any defaults with the user's choices.
  342. parse_args(argv)
  343. # Create tmp dir and clean up on exit with a callback.
  344. g_tmp_dir = tempfile.mkdtemp(suffix=".tmp_minicran")
  345. print "Created tmp directory: " + g_tmp_dir
  346. atexit.register(remove_tmp_dir)
  347. # Do the work.
  348. try:
  349. b = MinicranBuilder(g_print_only, g_output_dir, g_tmp_dir, g_platform, g_rversion, g_branch, g_buildnum)
  350. b.build()
  351. except KeyboardInterrupt:
  352. print("")
  353. pass
  354. # if __name__ == "__main__":
  355. # main(sys.argv)
  356. if __name__ == "__main__":
  357. b = CranDirectory("PACKAGES")
  358. b.emit()