1111from optparse import OptionParser
1212from datetime import datetime
1313
14- __version__ = '2.43 .0'
14+ __version__ = '2.60 .0'
1515
1616FORMAT = "%(message)s"
1717logging .basicConfig (format = FORMAT )
1818
1919logger = logging .getLogger ('testdroid' )
2020logger .setLevel (logging .INFO )
2121
22-
2322class RequestTimeout (Exception ):
2423
2524 def __init__ (self , msg ):
@@ -399,6 +398,14 @@ def upload_application_file(self, project_id, filename):
399398 path = "users/%s/projects/%s/files/application" % (me ['id' ], project_id )
400399 self .upload (path = path , filename = filename )
401400
401+ """ Upload application file to project
402+ """
403+ def upload_file (self , filename ):
404+ me = self .get_me ()
405+ path = "users/%s/files" % (me ['id' ])
406+ res = self .upload (path = path , filename = filename ).json ()
407+ print ("ID:%s Name:%s Size:%s" % (str (res ['id' ]).ljust (10 ), res ['name' ].ljust (15 ), res ['size' ]))
408+
402409 """ Upload test file to project
403410 """
404411 def upload_test_file (self , project_id , filename ):
@@ -627,6 +634,120 @@ def get_device_run_files(self, project_id, test_run_id, device_session_id, tags=
627634 def get_input_files (self , limit = 0 ):
628635 return self .get ("me/files?limit={}&filter=s_direction_eq_INPUT" .format (limit ))
629636
637+ """ Build API
638+ """
639+
640+ """ Print projects
641+ """
642+ def print_jobs (self , limit = 0 ):
643+ for job in self .get_jobs (limit )['data' ]:
644+ print ("%s %s \" %s\" " % (str (job ['id' ]).ljust (10 ), job ['name' ].ljust (15 ), job ['content' ]))
645+
646+ """ Print builds
647+ """
648+ def print_builds (self , job_id , limit = 0 ):
649+ print ("id buildNumber state status duration" )
650+ for build in self .get_builds (job_id , limit )['data' ]:
651+ print ("%s %s %s %s %s" % (str (build ['id' ]).ljust (12 ), str (build ['buildNumber' ]).ljust (5 ), build ['state' ].ljust (10 ), build ['status' ].ljust (10 ), build ['duration' ]))
652+
653+
654+
655+ """ Get builds from the job
656+ """
657+ def get_builds (self , job_id , limit = 0 ):
658+ return self .get ("me/jobs/{}/builds?limit={}" .format (job_id ,limit ))
659+
660+ """ Get job by id
661+ """
662+ def get_job (self , job_id ):
663+ return self .get ("me/jobs/{}" .format (job_id ))
664+
665+ """ Get build from the job
666+ """
667+ def get_build (self , job_id , build_id ):
668+ return self .get ("me/jobs/{}/builds/{}" .format (job_id , build_id ))
669+
670+ """ Get jobs
671+ """
672+ def get_jobs (self , limit = 0 ):
673+ return self .get ("me/jobs?limit={}" .format (limit ))
674+
675+ """ Create a job
676+ """
677+ def create_job (self , job_name , content , job_type = "BUILD" ):
678+ job = self .post (path = "me/jobs" , payload = {"name" : job_name , "content" : content , "type" : job_type })
679+ print (job )
680+
681+ logger .info ("Job %s: %s (%s) created" % (job ['id' ], job ['name' ], job ['type' ] ))
682+ return job
683+
684+ """ Create a build
685+ build_config:
686+ fileId: int
687+ executorId: int
688+ configuration: String
689+ resultsConfig: [resultsConfig]
690+
691+ resultsConfig:
692+ sourceName
693+ destinationName
694+ isDirectory
695+ fileUrlEnvVariable
696+
697+ usage: client.create_build(job_id, json.dumps({"fileId":123213...))
698+ """
699+ def create_build (self , job_id , build_config = {}):
700+ build = self .post (path = "me/jobs/{}/builds" .format (job_id ), payload = build_config , headers = {'Content-type' : 'application/json' , 'Accept' : 'application/json' })
701+ logger .info ("build %s: %s (%s) " % (build ['id' ], build ['buildNumber' ], build ['state' ] ))
702+ return build
703+
704+ """ Update job
705+ """
706+ def upload_job (self , job_id ,job_name , content ):
707+ job = self .post (path = "me/jobs/{}" .format (job_id ), payload = {"name" : job_name , "content" : content })
708+
709+ logger .info ("Job %s: %s (%s) created" % (job ['id' ], job ['name' ], job ['type' ] ))
710+ return job
711+
712+ """ Update job
713+ """
714+ def update_job (self , job_id ,job_name , content ):
715+ job = self .post (path = "me/jobs/{}" .format (job_id ), payload = {"name" : job_name , "content" : content })
716+
717+ logger .info ("Job %s: %s (%s) created" % (job ['id' ], job ['name' ], job ['type' ] ))
718+ return job
719+
720+ """ Delete job
721+ """
722+ def delete_job (self , job_id ):
723+ return self .delete ("me/jobs/{}" .format (job_id ))
724+
725+ """ Delete build
726+ """
727+ def delete_build (self , job_id , build_id ):
728+ return self .delete ("me/jobs/{}/builds/{}" .format (job_id , build_id ))
729+
730+ """ Get build output files
731+ """
732+ def download_build_output_files (self , job_id , build_id , results_folder = "results" , tags = None ):
733+ files = self .get ("me/jobs/{}/builds/{}/output-file-set/files{}" .format (job_id , build_id , "?tag[]=" .format (tags ) if tags else "" ))
734+ for file in files ['data' ]:
735+ if file ['state' ] == "READY" :
736+ full_path = "%s/%s" % (results_folder , file ['name' ])
737+ if not os .path .exists (results_folder ):
738+ os .makedirs (results_folder )
739+
740+ url = "me/files/%s/file" % (file ['id' ])
741+ prog = DownloadProgressBar ()
742+ self .download (url , full_path , callback = lambda pos , total : prog .update (int (pos ), int (total )))
743+ print ("" )
744+ else :
745+ logger .info ("File %s is not ready" % file ['name' ])
746+ if ( len (files ['data' ]) == 0 ):
747+ logger .info ("No files to download" )
748+ logger .info ("" )
749+
750+
630751 """ Downloads test run files to a directory hierarchy
631752 """
632753 def download_test_run (self , project_id , test_run_id ):
@@ -736,6 +857,7 @@ def format_epilog(self, formatter):
736857 upload-application <project-id> <filename> Upload application to project
737858 upload-test <project-id> <filename> Upload test file to project
738859 upload-data <project-id> <filename> Upload additional data file to project
860+ upload-file <filename> Upload to "Files"
739861 set-project-config <project-id> <config-json>
740862 Change the project config parameters as facilitated by the API:
741863 http://docs.testdroid.com/_pages/client.html#project-config
@@ -788,6 +910,7 @@ def get_commands(self):
788910 "upload-application" : self .upload_application_file ,
789911 "upload-test" : self .upload_test_file ,
790912 "upload-data" : self .upload_data_file ,
913+ "upload-file" : self .upload_file ,
791914 "set-project-config" : self .set_project_config ,
792915 "start-test-run" : self .start_test_run ,
793916 "start-test-run-using-config" : self .start_test_run_using_config ,
@@ -799,7 +922,15 @@ def get_commands(self):
799922 "device-run-files" : self .get_device_run_files ,
800923 "list-input-files" : self .print_input_files ,
801924 "download-test-run" : self .download_test_run ,
802- "download-test-screenshots" : self .download_test_screenshots
925+ "jobs" : self .print_jobs ,
926+ "builds" : self .print_builds ,
927+ "create-job" : self .create_job ,
928+ "update-job" : self .update_job ,
929+ "create-build" : self .create_build ,
930+ "delete-job" : self .delete_job ,
931+ "delete-build" : self .delete_build ,
932+ "download-builds-files" : self .download_build_output_files
933+
803934 }
804935 return commands
805936
0 commit comments