Skip to content

Commit a02ced6

Browse files
author
mars
committed
latest uploader
1 parent f2be160 commit a02ced6

1 file changed

Lines changed: 74 additions & 34 deletions

File tree

Tools/Heavy/uploader.py

Lines changed: 74 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
#!/usr/bin/python
2-
3-
# Copyright 2015 Section6. All Rights Reserved.
1+
# Copyright 2015,2016 Enzien Audio, Ltd. All Rights Reserved.
42

53
import argparse
64
import getpass
@@ -26,14 +24,19 @@ class Colours:
2624
underline = "\033[4m"
2725
end = "\033[0m"
2826

27+
# the maxmimum file upload size of 1MB
28+
__HV_MAX_UPLOAD_SIZE = 1024*1024
29+
2930
def __zip_dir(in_dir, zip_path, file_filter=None):
31+
"""Recursively zip an entire directory with an optional file filter
32+
"""
3033
zf = zipfile.ZipFile(zip_path, mode="w", compression=zipfile.ZIP_DEFLATED)
3134
for subdir, dirs, files in os.walk(in_dir):
32-
for file in files:
33-
if (file_filter is None) or (len(file_filter) > 0 and file.lower().split(".")[-1] in file_filter):
35+
for f in files:
36+
if (file_filter is None) or (f.lower().split(".")[-1] in file_filter):
3437
zf.write(
35-
filename=os.path.join(subdir,file),
36-
arcname=os.path.relpath(os.path.join(subdir,file), start=in_dir))
38+
filename=os.path.join(subdir,f),
39+
arcname=os.path.relpath(os.path.join(subdir,f), start=in_dir))
3740
return zip_path
3841

3942
def __unzip(zip_path, target_dir):
@@ -46,25 +49,36 @@ def main():
4649
description="Compiles a Pure Data file.")
4750
parser.add_argument(
4851
"input_dir",
49-
help="A directory containing _main.pd. The entire directory will be uploaded.")
52+
help="A directory containing _main.pd. All .pd files in the directory structure will be uploaded.")
5053
parser.add_argument(
5154
"-n", "--name",
5255
default="heavy",
53-
help="Patch name. If it doesn't exist, the uploader will fail. Make sure that it exists on the Heavy website.")
56+
help="Patch name. If it doesn't exist on the Heavy site, the uploader will fail.")
5457
parser.add_argument(
5558
"-g", "--gen",
5659
nargs="+",
5760
default=["c"],
58-
help="List of generator outputs. Currently supported generators are 'c' and 'js'.")
61+
help="List of generator outputs. Currently supported generators are "
62+
"'c', 'js', 'pdext', 'pdext-osx', 'unity', 'unity-osx', "
63+
"'unity-win-x86', 'unity-win-x86_64', 'wwise', 'wwise-win-x86_64', "
64+
"'vst2' ,'vst2-osx', and 'vst2-win-x86_64'.")
5965
parser.add_argument(
6066
"-b",
61-
help="All files will be placed in the output directory, placed in their own subdirectory corresonding to the generator name.",
67+
help="All files will be placed in the output directory, placed in their own subdirectory corresponding to the generator name.",
68+
action="count")
69+
parser.add_argument(
70+
"-y",
71+
help="Extract only the generated C files. Static files are deleted. "
72+
"Only effective for the 'c' generator.",
6273
action="count")
6374
parser.add_argument(
6475
"-o", "--out",
6576
nargs="+",
6677
default=["./"], # by default
6778
help="List of destination directories for retrieved files. Order should be the same as for --gen.")
79+
parser.add_argument(
80+
"-r", "--release",
81+
help="Optionally request a specific release of Heavy to use while compiling.")
6882
parser.add_argument(
6983
"-d", "--domain",
7084
default="https://enzienaudio.com",
@@ -79,7 +93,7 @@ def main():
7993
action="count")
8094
parser.add_argument(
8195
"--noverify",
82-
help="Don't verify the SSL connection. Generally a bad idea.",
96+
help="Don't verify the SSL connection. This is generally a very bad idea.",
8397
action="count")
8498
parser.add_argument(
8599
"-v", "--verbose",
@@ -98,17 +112,13 @@ def main():
98112
# token should be stored in ~/.heavy/token
99113
token_path = os.path.expanduser(os.path.join("~/", ".heavy", "token"))
100114

101-
if args.token != None:
115+
if args.token is not None:
102116
# check if token has been passed as a command line arg...
103-
post_data["credentials"] = {
104-
"token": args.token
105-
}
117+
post_data["credentials"] = {"token": args.token}
106118
elif os.path.exists(token_path) and not args.z:
107119
# ...or if it is stored in the user's home directory
108120
with open(token_path, "r") as f:
109-
post_data["credentials"] = {
110-
"token": f.read()
111-
}
121+
post_data["credentials"] = {"token": f.read()}
112122
else:
113123
# otherwise, get the username and password
114124
post_data["credentials"] = {
@@ -118,6 +128,10 @@ def main():
118128

119129
tick = time.time()
120130

131+
# parse the optional release argument
132+
if args.release:
133+
post_data["release"] = args.release
134+
121135
# make a temporary directory
122136
temp_dir = tempfile.mkdtemp(prefix="lroyal-")
123137

@@ -129,16 +143,25 @@ def main():
129143
args.input_dir,
130144
os.path.join(temp_dir, "archive.zip"),
131145
file_filter={"pd"})
146+
if os.stat(zip_path).st_size > __HV_MAX_UPLOAD_SIZE:
147+
raise Exception("The target directory, zipped, is {0} bytes. The maximum upload size of 1MB.".format(
148+
os.stat(zip_path).st_size))
132149
except Exception as e:
133-
print e
150+
print "{0}Error:{1} {2}".format(Colours.red, Colours.end, e)
134151
shutil.rmtree(temp_dir) # clean up the temporary directory
135152
return
136153

137154
post_data["name"] = args.name
138155

139156
# the outputs to generate (always include c)
140-
__SUPPORTED_GENERATOR_SET = {"c", "js"}
141-
post_data["gen"] = list(({"c"} | set(args.gen)) & __SUPPORTED_GENERATOR_SET)
157+
__SUPPORTED_GENERATOR_SET = {
158+
"c", "js",
159+
"pdext", "pdext-osx",
160+
"unity", "unity-osx", "unity-win-x86", "unity-win-x86_64",
161+
"wwise", "wwise-win-x86_64",
162+
"vst2", "vst2-osx", "vst2-win-x86_64",
163+
}
164+
post_data["gen"] = list(({"c"} | {s.lower() for s in set(args.gen)}) & __SUPPORTED_GENERATOR_SET)
142165

143166
# upload the job, get the response back
144167
# NOTE(mhroth): multipart-encoded file can only be sent as a flat dictionary,
@@ -151,6 +174,7 @@ def main():
151174

152175
if r.status_code != requests.codes.ok:
153176
shutil.rmtree(temp_dir) # clean up the temporary directory
177+
print "Getting a weird error? Get the latest uploader at https://enzienaudio.com/static/uploader.py"
154178
r.raise_for_status() # raise an exception
155179

156180
# decode the JSON API response
@@ -203,7 +227,9 @@ def main():
203227
"type": "file"
204228
}
205229
],
206-
"warnings": [],
230+
"warnings": [
231+
{"details": "blah blah blah"}
232+
],
207233
"meta": {
208234
"token": "11AS0qPRmjTUHEMSovPEvzjodnzB1xaz"
209235
}
@@ -219,25 +245,32 @@ def main():
219245

220246
# update the api token, if present
221247
if "token" in reply_json.get("meta",{}) and not args.x:
222-
if args.token == None:
248+
if args.token is not None:
249+
if reply_json["meta"]["token"] != args.token:
250+
print "WARNING: Token returned by API is not the same as the "
251+
"token supplied at the command line. (old = %s, new = %s)".format(
252+
args.token,
253+
reply_json["meta"]["token"])
254+
else:
223255
if not os.path.exists(os.path.dirname(token_path)):
224-
os.makedirs(os.path.dirname(token_path)) # ensure that the .heavy directory exists
256+
# ensure that the .heavy directory exists
257+
os.makedirs(os.path.dirname(token_path))
225258
with open(token_path, "w") as f:
226259
f.write(reply_json["meta"]["token"])
227-
os.chmod(token_path, stat.S_IRUSR | stat.S_IWUSR) # force rw------- permissions on the file
228-
else:
229-
if reply_json["meta"]["token"] != args.token:
230-
print "WARNING: Could not update API token. (old = %s, new = %s)" % (args.token, reply_json["meta"]["token"])
260+
# force rw------- permissions on the file
261+
os.chmod(token_path, stat.S_IRUSR | stat.S_IWUSR)
231262

232263
# print any warnings
233-
for x in r_json["warnings"]:
234-
print "{0}Warning:{1} {2}".format(Colours.yellow, Colours.end, x["detail"])
264+
for i,x in enumerate(r_json.get("warnings",[])):
265+
print "{3}) {0}Warning:{1} {2}".format(
266+
Colours.yellow, Colours.end, x["detail"], i+1)
235267

236268
# check for errors
237269
if len(r_json.get("errors",[])) > 0:
238270
shutil.rmtree(temp_dir) # clean up the temporary directory
239-
for x in r_json["errors"]:
240-
print "{0}Error:{1} {2}".format(Colours.red, Colours.end, x["detail"])
271+
for i,x in enumerate(r_json["errors"]):
272+
print "{3}) {0}Error:{1} {2}".format(
273+
Colours.red, Colours.end, x["detail"], i+1)
241274
return
242275

243276
# retrieve all requested files
@@ -264,6 +297,12 @@ def main():
264297
os.makedirs(target_dir) # ensure that the output directory exists
265298
__unzip(c_zip_path, target_dir)
266299

300+
if g == "c" and args.y:
301+
keep_files = ("_{0}.h".format(args.name), "_{0}.c".format(args.name))
302+
for f in os.listdir(target_dir):
303+
if not f.endswith(keep_files):
304+
os.remove(os.path.join(target_dir, f));
305+
267306
print "{0} files placed in {1}".format(g, target_dir)
268307
else:
269308
print "{0}Warning:{1} {2} files could not be retrieved.".format(
@@ -273,8 +312,9 @@ def main():
273312
# delete the temporary directory
274313
shutil.rmtree(temp_dir)
275314

276-
print "Job URL", reply_json["data"]["links"]["self"]
315+
print "Job URL:", reply_json["data"]["links"]["self"]
277316
print "Total request time: {0}ms".format(int(1000.0*(time.time()-tick)))
317+
print "Heavy release:", reply_json.get("meta",{}).get("release", "default")
278318

279319
def __get_file_url_for_generator(json_api, g):
280320
"""Returns the file link for a specific generator.

0 commit comments

Comments
 (0)