wandbox_deploy.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. #! /usr/bin/env python
  2. # This script uploads a directory to Wandbox (http://melpon.org/wandbox),
  3. # which is an online compiler environment, and prints a permalink to the
  4. # uploaded code. We use this to provide a "Try it online" version of the
  5. # library to make the barrier to entry as low as possible.
  6. #
  7. # This script was adapted from the script proposed in
  8. # https://github.com/melpon/wandbox/issues/153.
  9. #
  10. # To know how to use this script: ./wandbox.py --help
  11. #
  12. # Copyright Louis Dionne 2013-2016
  13. # Distributed under the Boost Software License, Version 1.0.
  14. # (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  15. import argparse
  16. import fnmatch
  17. import json
  18. import os
  19. import re
  20. import urllib2
  21. # Strips C and C++ comments from the given string.
  22. #
  23. # Copied from http://stackoverflow.com/a/241506/627587.
  24. def strip_comments(text):
  25. def replacer(match):
  26. s = match.group(0)
  27. if s.startswith('/'):
  28. return " " # note: a space and not an empty string
  29. else:
  30. return s
  31. pattern = re.compile(
  32. r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
  33. re.DOTALL | re.MULTILINE
  34. )
  35. return re.sub(pattern, replacer, text)
  36. # Post the given JSON data to Wandbox's API, and return the result
  37. # as a JSON object.
  38. def upload(options):
  39. request = urllib2.Request('https://wandbox.org/api/compile.json')
  40. request.add_header('Content-Type', 'application/json')
  41. response = urllib2.urlopen(request, json.dumps(options))
  42. return json.loads(response.read())
  43. # Returns a list of the '.hpp' headers in the given directory and in
  44. # subdirectories.
  45. #
  46. # The path must be absolute, and the returned paths are all absolute too.
  47. def headers(path):
  48. return [
  49. os.path.join(dir, file)
  50. for (dir, _, files) in os.walk(path)
  51. for file in fnmatch.filter(files, "*.hpp")
  52. ]
  53. def main():
  54. parser = argparse.ArgumentParser(description=
  55. """Upload a directory to Wandbox (http://melpon.org/wandbox).
  56. On success, the program prints a permalink to the uploaded
  57. directory on Wandbox and returns 0. On error, it prints the
  58. response from the Wandbox API and returns 1.
  59. Note that the comments are stripped from all the headers in the
  60. uploaded directory.
  61. """
  62. )
  63. parser.add_argument('directory', type=str, help=
  64. """A directory to upload to Wandbox.
  65. The path may be either absolute or relative to the current directory.
  66. However, the names of the files uploaded to Wandbox will all be
  67. relative to this directory. This way, one can easily specify the
  68. directory to be '/some/project/include', and the uploaded files
  69. will be uploaded as-if they were rooted at '/some/project/include'
  70. """)
  71. parser.add_argument('main', type=str, help=
  72. """The main source file.
  73. The path may be either absolute or relative to the current directory.
  74. """
  75. )
  76. args = parser.parse_args()
  77. directory = os.path.abspath(args.directory)
  78. if not os.path.exists(directory):
  79. raise Exception("'%s' is not a valid directory" % args.directory)
  80. cpp = os.path.abspath(args.main)
  81. if not os.path.exists(cpp):
  82. raise Exception("'%s' is not a valid file name" % args.main)
  83. response = upload({
  84. 'code': open(cpp).read(),
  85. 'codes': [{
  86. 'file': os.path.relpath(header, directory).replace('\\', '/'),
  87. 'code': strip_comments(open(header).read())
  88. } for header in headers(directory)],
  89. 'options': 'warning,c++14',
  90. 'compiler': 'clang-3.6.0',
  91. 'save': True,
  92. 'compiler-option-raw': '-I.'
  93. })
  94. if response['status'] == '0':
  95. print response['url']
  96. return 0
  97. else:
  98. print response
  99. return 1
  100. exit(main())