1- #!/usr/bin/python
2-
3- # Copyright 2015 Section6. All Rights Reserved.
1+ # Copyright 2015,2016 Enzien Audio, Ltd. All Rights Reserved.
42
53import argparse
64import 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+
2930def __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
3942def __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
279319def __get_file_url_for_generator (json_api , g ):
280320 """Returns the file link for a specific generator.
0 commit comments