Mercurial > hg > beaglert
comparison scripts/hvresources/uploader.py @ 229:c768ed1055b0 mergingClockSync
Fixed heavy-midi and updated uploader.py
author | Giulio Moro <giuliomoro@yahoo.it> |
---|---|
date | Sat, 09 Apr 2016 00:52:57 +0100 |
parents | 5bcf04234f80 |
children | df710a88e355 83e1acf38d35 |
comparison
equal
deleted
inserted
replaced
228:a0a7f00cf98d | 229:c768ed1055b0 |
---|---|
1 #!/usr/bin/python | 1 # Copyright 2015,2016 Enzien Audio, Ltd. All Rights Reserved. |
2 | |
3 # Copyright 2015 Section6. All Rights Reserved. | |
4 | 2 |
5 import argparse | 3 import argparse |
6 import getpass | 4 import getpass |
7 import json | 5 import json |
8 import os | 6 import os |
11 import stat | 9 import stat |
12 import tempfile | 10 import tempfile |
13 import time | 11 import time |
14 import urlparse | 12 import urlparse |
15 import zipfile | 13 import zipfile |
16 import sys | |
17 | 14 |
18 class Colours: | 15 class Colours: |
19 purple = "\033[95m" | 16 purple = "\033[95m" |
20 cyan = "\033[96m" | 17 cyan = "\033[96m" |
21 dark_cyan = "\033[36m" | 18 dark_cyan = "\033[36m" |
45 def main(): | 42 def main(): |
46 parser = argparse.ArgumentParser( | 43 parser = argparse.ArgumentParser( |
47 description="Compiles a Pure Data file.") | 44 description="Compiles a Pure Data file.") |
48 parser.add_argument( | 45 parser.add_argument( |
49 "input_dir", | 46 "input_dir", |
50 help="A directory containing _main.pd. The entire directory will be uploaded.") | 47 help="A directory containing _main.pd. All .pd files in the directory structure will be uploaded.") |
51 parser.add_argument( | 48 parser.add_argument( |
52 "-n", "--name", | 49 "-n", "--name", |
53 default="heavy", | 50 default="heavy", |
54 help="Patch name. If it doesn't exist, the uploader will fail. Make sure that it exists on the Heavy website.") | 51 help="Patch name. If it doesn't exist on the Heavy site, the uploader will fail.") |
55 parser.add_argument( | 52 parser.add_argument( |
56 "-g", "--gen", | 53 "-g", "--gen", |
57 nargs="+", | 54 nargs="+", |
58 default=["c"], | 55 default=["c"], |
59 help="List of generator outputs. Currently supported generators are 'c' and 'js'.") | 56 help="List of generator outputs. Currently supported generators are " |
57 "'c', 'js', 'pdext', 'pdext-osx', 'unity', 'unity-osx', " | |
58 "'unity-win-x86', 'unity-win-x86_64', 'wwise', 'wwise-win-x86_64', " | |
59 "'vst2' ,'vst2-osx', and 'vst2-win-x86_64'.") | |
60 parser.add_argument( | 60 parser.add_argument( |
61 "-b", | 61 "-b", |
62 help="All files will be placed in the output directory, placed in their own subdirectory corresonding to the generator name.", | 62 help="All files will be placed in the output directory, placed in their own subdirectory corresponding to the generator name.", |
63 action="count") | |
64 parser.add_argument( | |
65 "-y", | |
66 help="Extract only the generated C files. Static files are deleted. " | |
67 "Only effective for the 'c' generator.", | |
63 action="count") | 68 action="count") |
64 parser.add_argument( | 69 parser.add_argument( |
65 "-o", "--out", | 70 "-o", "--out", |
66 nargs="+", | 71 nargs="+", |
67 default=["./"], # by default | 72 default=["./"], # by default |
78 "-z", | 83 "-z", |
79 help="Force the use of a password, regardless of saved token.", | 84 help="Force the use of a password, regardless of saved token.", |
80 action="count") | 85 action="count") |
81 parser.add_argument( | 86 parser.add_argument( |
82 "--noverify", | 87 "--noverify", |
83 help="Don't verify the SSL connection. Generally a bad idea.", | 88 help="Don't verify the SSL connection. This is generally a very bad idea.", |
84 action="count") | 89 action="count") |
85 parser.add_argument( | 90 parser.add_argument( |
86 "-v", "--verbose", | 91 "-v", "--verbose", |
87 help="Show debugging information.", | 92 help="Show debugging information.", |
88 action="count") | 93 action="count") |
94 parser.add_argument( | |
95 "-t", "--token", | |
96 help="Use the specified token.", | |
97 ) | |
89 args = parser.parse_args() | 98 args = parser.parse_args() |
90 | 99 |
91 domain = args.domain or "https://enzienaudio.com" | 100 domain = args.domain or "https://enzienaudio.com" |
92 | 101 |
93 post_data = {} | 102 post_data = {} |
94 | 103 |
95 # token should be stored in ~/.heavy/token | 104 # token should be stored in ~/.heavy/token |
96 token_path = os.path.expanduser(os.path.join("~/", ".heavy", "token")) | 105 token_path = os.path.expanduser(os.path.join("~/", ".heavy", "token")) |
97 if os.path.exists(token_path) and not args.z: | 106 |
107 if args.token is not None: | |
108 # check if token has been passed as a command line arg... | |
109 post_data["credentials"] = {"token": args.token} | |
110 elif os.path.exists(token_path) and not args.z: | |
111 # ...or if it is stored in the user's home directory | |
98 with open(token_path, "r") as f: | 112 with open(token_path, "r") as f: |
99 post_data["credentials"] = { | 113 post_data["credentials"] = {"token": f.read()} |
100 "token": f.read() | |
101 } | |
102 else: | 114 else: |
103 # otherwise, get the username and password | 115 # otherwise, get the username and password |
104 post_data["credentials"] = { | 116 post_data["credentials"] = { |
105 "username": raw_input("Enter username: "), | 117 "username": raw_input("Enter username: "), |
106 "password": getpass.getpass("Enter password: ") | 118 "password": getpass.getpass("Enter password: ") |
125 return | 137 return |
126 | 138 |
127 post_data["name"] = args.name | 139 post_data["name"] = args.name |
128 | 140 |
129 # the outputs to generate (always include c) | 141 # the outputs to generate (always include c) |
130 __SUPPORTED_GENERATOR_SET = {"c", "js"} | 142 __SUPPORTED_GENERATOR_SET = { |
143 "c", "js", | |
144 "pdext", "pdext-osx", | |
145 "unity", "unity-osx", "unity-win-x86", "unity-win-x86_64", | |
146 "wwise", "wwise-win-x86_64", | |
147 "vst2", "vst2-osx", "vst2-win-x86_64", | |
148 } | |
131 post_data["gen"] = list(({"c"} | set(args.gen)) & __SUPPORTED_GENERATOR_SET) | 149 post_data["gen"] = list(({"c"} | set(args.gen)) & __SUPPORTED_GENERATOR_SET) |
132 | 150 |
133 # upload the job, get the response back | 151 # upload the job, get the response back |
134 # NOTE(mhroth): multipart-encoded file can only be sent as a flat dictionary, | 152 # NOTE(mhroth): multipart-encoded file can only be sent as a flat dictionary, |
135 # but we want to send a json encoded deep dictionary. So we do a bit of a hack. | 153 # but we want to send a json encoded deep dictionary. So we do a bit of a hack. |
139 files={"file": (os.path.basename(zip_path), open(zip_path, "rb"), "application/zip")}, | 157 files={"file": (os.path.basename(zip_path), open(zip_path, "rb"), "application/zip")}, |
140 verify=False if args.noverify else True) | 158 verify=False if args.noverify else True) |
141 | 159 |
142 if r.status_code != requests.codes.ok: | 160 if r.status_code != requests.codes.ok: |
143 shutil.rmtree(temp_dir) # clean up the temporary directory | 161 shutil.rmtree(temp_dir) # clean up the temporary directory |
162 print "Getting a weird error? Get the latest uploader at https://enzienaudio.com/static/uploader.py" | |
144 r.raise_for_status() # raise an exception | 163 r.raise_for_status() # raise an exception |
145 | 164 |
146 # decode the JSON API response | 165 # decode the JSON API response |
147 r_json = r.json() | 166 r_json = r.json() |
148 | 167 |
191 }, | 210 }, |
192 "mime": "application/zip", | 211 "mime": "application/zip", |
193 "type": "file" | 212 "type": "file" |
194 } | 213 } |
195 ], | 214 ], |
196 "warnings": [], | 215 "warnings": [ |
216 {"details": "blah blah blah"} | |
217 ], | |
197 "meta": { | 218 "meta": { |
198 "token": "11AS0qPRmjTUHEMSovPEvzjodnzB1xaz" | 219 "token": "11AS0qPRmjTUHEMSovPEvzjodnzB1xaz" |
199 } | 220 } |
200 } | 221 } |
201 """ | 222 """ |
207 indent=2, | 228 indent=2, |
208 separators=(",", ": ")) | 229 separators=(",", ": ")) |
209 | 230 |
210 # update the api token, if present | 231 # update the api token, if present |
211 if "token" in reply_json.get("meta",{}) and not args.x: | 232 if "token" in reply_json.get("meta",{}) and not args.x: |
212 if not os.path.exists(os.path.dirname(token_path)): | 233 if args.token is not None: |
213 os.makedirs(os.path.dirname(token_path)) # ensure that the .heavy directory exists | 234 if reply_json["meta"]["token"] != args.token: |
214 with open(token_path, "w") as f: | 235 print "WARNING: Token returned by API is not the same as the " |
215 f.write(reply_json["meta"]["token"]) | 236 "token supplied at the command line. (old = %s, new = %s)".format( |
216 os.chmod(token_path, stat.S_IRUSR | stat.S_IWUSR) # force rw------- permissions on the file | 237 args.token, |
238 reply_json["meta"]["token"]) | |
239 else: | |
240 if not os.path.exists(os.path.dirname(token_path)): | |
241 # ensure that the .heavy directory exists | |
242 os.makedirs(os.path.dirname(token_path)) | |
243 with open(token_path, "w") as f: | |
244 f.write(reply_json["meta"]["token"]) | |
245 # force rw------- permissions on the file | |
246 os.chmod(token_path, stat.S_IRUSR | stat.S_IWUSR) | |
217 | 247 |
218 # print any warnings | 248 # print any warnings |
219 for x in r_json["warnings"]: | 249 for i,x in enumerate(r_json.get("warnings",[])): |
220 print "{0}Warning:{1} {2}".format(Colours.yellow, Colours.end, x["detail"]) | 250 print "{3}) {0}Warning:{1} {2}".format( |
251 Colours.yellow, Colours.end, x["detail"], i+1) | |
221 | 252 |
222 # check for errors | 253 # check for errors |
223 if len(r_json.get("errors",[])) > 0: | 254 if len(r_json.get("errors",[])) > 0: |
224 shutil.rmtree(temp_dir) # clean up the temporary directory | 255 shutil.rmtree(temp_dir) # clean up the temporary directory |
225 for x in r_json["errors"]: | 256 for i,x in enumerate(r_json["errors"]): |
226 print "{0}Error:{1} {2}".format(Colours.red, Colours.end, x["detail"]) | 257 print "{3}) {0}Error:{1} {2}".format( |
227 sys.exit(1) | 258 Colours.red, Colours.end, x["detail"], i+1) |
228 return | 259 return |
229 | 260 |
230 # retrieve all requested files | 261 # retrieve all requested files |
231 for i,g in enumerate(args.gen): | 262 for i,g in enumerate(args.gen): |
232 file_url = __get_file_url_for_generator(reply_json, g) | 263 file_url = __get_file_url_for_generator(reply_json, g) |
249 target_dir = os.path.abspath(os.path.expanduser(args.out[i])) | 280 target_dir = os.path.abspath(os.path.expanduser(args.out[i])) |
250 if not os.path.exists(target_dir): | 281 if not os.path.exists(target_dir): |
251 os.makedirs(target_dir) # ensure that the output directory exists | 282 os.makedirs(target_dir) # ensure that the output directory exists |
252 __unzip(c_zip_path, target_dir) | 283 __unzip(c_zip_path, target_dir) |
253 | 284 |
285 if g == "c" and args.y: | |
286 keep_files = ("_{0}.h".format(args.name), "_{0}.c".format(args.name)) | |
287 for f in os.listdir(target_dir): | |
288 if not f.endswith(keep_files): | |
289 os.remove(os.path.join(target_dir, f)); | |
290 | |
254 print "{0} files placed in {1}".format(g, target_dir) | 291 print "{0} files placed in {1}".format(g, target_dir) |
255 else: | 292 else: |
256 print "{0}Warning:{1} {2} files could not be retrieved.".format( | 293 print "{0}Warning:{1} {2} files could not be retrieved.".format( |
257 Colours.yellow, Colours.end, | 294 Colours.yellow, Colours.end, |
258 g) | 295 g) |
259 | 296 |
260 # delete the temporary directory | 297 # delete the temporary directory |
261 shutil.rmtree(temp_dir) | 298 shutil.rmtree(temp_dir) |
262 | 299 |
263 print "Job URL", reply_json["data"]["links"]["self"] | 300 print "Job URL:", reply_json["data"]["links"]["self"] |
264 print "Total request time: {0}ms".format(int(1000.0*(time.time()-tick))) | 301 print "Total request time: {0}ms".format(int(1000.0*(time.time()-tick))) |
265 | 302 print "Heavy version:", reply_json["meta"]["version"] |
266 sys.exit(0) | |
267 | 303 |
268 def __get_file_url_for_generator(json_api, g): | 304 def __get_file_url_for_generator(json_api, g): |
269 """Returns the file link for a specific generator. | 305 """Returns the file link for a specific generator. |
270 Returns None if no link could be found. | 306 Returns None if no link could be found. |
271 """ | 307 """ |