def test_insert(self): # A job can not be created without a jobtype, create one first jobtype = JobType() jobtype.name = "foo" jobtype.description = "this is a job type" jobtype_version = JobTypeVersion() jobtype_version.jobtype = jobtype jobtype_version.version = 1 jobtype_version.classname = "Foobar" jobtype_version.code = (""" class Foobar(JobType): pass""").encode("utf-8") db.session.add(jobtype_version) queue = JobQueue() queue.name = "FooQueue" job = Job() job.title = "Test Job" job.jobtype_version = jobtype_version job.queue = queue tag = Tag() tag.jobs = [job] tag.tag = "foo456" db.session.add_all([tag, job]) db.session.commit() model_id = tag.id job_id = job.id db.session.remove() result = Tag.query.filter_by(id=model_id).first() self.assertEqual(result.tag, "foo456") self.assertEqual(result.jobs[0].id, job_id)
def test_insert(self): jobtype = JobType() jobtype.name = "foo" jobtype.description = "this is a job type" jobtype_version = JobTypeVersion() jobtype_version.jobtype = jobtype jobtype_version.version = 1 jobtype_version.classname = "Foobar" jobtype_version.code = (""" class Foobar(JobType): pass""").encode("utf-8") db.session.add(jobtype_version) job = Job() job.title = "Test Job" job.jobtype_version = jobtype_version task = Task(state=WorkState.DONE, priority=404, frame=1, last_error="foobar", job=job) db.session.add(task) db.session.commit() task_id = task.id db.session.remove() searched = Task.query.filter_by(id=task_id).first() self.assertIsNotNone(searched) self.assertEqual(searched.state, WorkState.DONE) self.assertEqual(searched.priority, 404) self.assertEqual(searched.attempts, 0) self.assertEqual(searched.frame, 1)
def test_insert(self): jobtype = JobType() jobtype.name = "foo" jobtype.description = "this is a job type" jobtype_version = JobTypeVersion() jobtype_version.jobtype = jobtype jobtype_version.version = 1 jobtype_version.classname = "Foobar" jobtype_version.code = (""" class Foobar(JobType): pass""").encode("utf-8") db.session.add(jobtype_version) job = Job() job.title = "Test Job" job.jobtype_version = jobtype_version task = Task( state=WorkState.DONE, priority=404, frame=1, last_error="foobar", job=job) db.session.add(task) db.session.commit() task_id = task.id db.session.remove() searched = Task.query.filter_by(id=task_id).first() self.assertIsNotNone(searched) self.assertEqual(searched.state, WorkState.DONE) self.assertEqual(searched.priority, 404) self.assertEqual(searched.attempts, 0) self.assertEqual(searched.frame, 1)
def create_jobtype_version(self): jobtype = JobType() jobtype.name = "foo" jobtype.description = "this is a job type" jobtype_version = JobTypeVersion() jobtype_version.jobtype = jobtype jobtype_version.version = 1 jobtype_version.classname = "Foobar" jobtype_version.code = (""" class Foobar(JobType): pass""").encode("utf-8") db.session.add(jobtype_version) db.session.flush() return jobtype_version
def test_insert(self): # A job can not be created without a jobtype, create one first jobtype = JobType() jobtype.name = "foo" jobtype.description = "this is a job type" jobtype.classname = "Foobar" jobtype.code = dedent(""" class Foobar(JobType): pass""").encode("utf-8") jobtype.mode = JobTypeLoadMode.OPEN db.session.add(jobtype) job = Job() job.job_type = jobtype tag = Tag() tag.jobs = [job] tag.tag = "foo456" db.session.add_all([tag, job]) db.session.commit() model_id = tag.id job_id = job.id db.session.remove() result = Tag.query.filter_by(id=model_id).first() self.assertEqual(result.tag, "foo456") self.assertEqual(result.jobs[0].id, job_id)
def test_basic_insert(self): value_name = "foo" value_description = "this is a job type" value_classname = "Foobar" value_code = dedent(""" class %s(JobType): pass""" % value_classname) value_mode = JobTypeLoadMode.OPEN # create jobtype jobtype = JobType() jobtype.name = value_name jobtype.description = value_description jobtype.classname = value_classname jobtype.code = value_code jobtype.mode = value_mode db.session.add(jobtype) db.session.commit() # store id and remove the session jobtypeid = jobtype.id db.session.remove() jobtype = JobType.query.filter_by(id=jobtypeid).first() self.assertEqual(jobtype.name, value_name) self.assertEqual(jobtype.description, value_description) self.assertEqual(jobtype.classname, value_classname) self.assertEqual(jobtype.code, value_code) self.assertEqual(jobtype.mode, value_mode)
def test_insert(self): # A job can not be created without a jobtype, create one first jobtype = JobType() jobtype.name = "foo" jobtype.description = "this is a job type" jobtype.classname = "Foobar" jobtype.code = dedent(""" class Foobar(JobType): pass""").encode("utf-8") jobtype.mode = JobTypeLoadMode.OPEN db.session.add(jobtype) job = Job() job.job_type = jobtype software = Software() software.jobs = [job] software.software = "foo" db.session.add_all([job, software]) db.session.commit() job_id = job.id software_id = software.id db.session.remove() software = Software.query.filter_by(id=software_id).first() self.assertEqual(software.jobs[0].id, job_id) self.assertEqual(software.software, "foo") self.assertEqual(software.version, "any")
def test_unique(self): # A job can not be created without a jobtype, create one first jobtype = JobType() jobtype.name = "foo" jobtype.description = "this is a job type" jobtype.classname = "Foobar" jobtype.code = dedent(""" class Foobar(JobType): pass""").encode("utf-8") db.session.add(jobtype) job = Job() job.job_type = jobtype software = Software() software.software = "foo" requirementA = JobSoftwareRequirement() requirementB = JobSoftwareRequirement() requirementA.job = job requirementA.software = software requirementB.job = job requirementB.software = software db.session.add_all([job, requirementA, requirementB]) with self.assertRaises(DatabaseError): db.session.commit()
def test_insert(self): # A job can not be created without a jobtype, create one first jobtype = JobType() jobtype.name = "foo" jobtype.description = "this is a job type" jobtype_version = JobTypeVersion() jobtype_version.jobtype = jobtype jobtype_version.version = 1 jobtype_version.classname = "Foobar" jobtype_version.code = (""" class Foobar(JobType): pass""").encode("utf-8") db.session.add(jobtype_version) queue = JobQueue() queue.name = "FooQueue" job = Job() job.title = "Test Job" job.jobtype_version = jobtype_version job.queue = queue # Software requirement needs a software first software = Software() software.software = "foo" requirement = JobSoftwareRequirement() requirement.job = job requirement.software = software db.session.add(job) db.session.commit() job_id = job.id requirement_id = requirement.id requirement2 = JobSoftwareRequirement.query.\ filter_by(id=requirement_id).first() self.assertEqual(requirement.job.id, job_id) self.assertEqual(requirement2.software.software, "foo") self.assertEqual(requirement2.min_version, None) self.assertEqual(requirement2.max_version, None)
def test_clear_last_error(self): jobtype = JobType() jobtype.name = "foo" jobtype.description = "this is a job type" jobtype_version = JobTypeVersion() jobtype_version.jobtype = jobtype jobtype_version.version = 1 jobtype_version.classname = "Foobar" jobtype_version.code = (""" class Foobar(JobType): pass""").encode("utf-8") db.session.add(jobtype_version) job = Job() job.title = "Test Job" job.jobtype_version = jobtype_version task = Task(frame=1, job=job, last_error="foobar") db.session.add(task) db.session.commit() db.session.add(task) task.state = WorkState.DONE self.assertIsNone(task.last_error)
def test_before_insert_parent_class(self): value_name = "foo" value_description = "this is a job type" value_classname = "Foobar" value_code = dedent(""" class %s(object): pass""" % value_classname).encode("utf-8") # create jobtype jobtype = JobType() jobtype.name = value_name jobtype.description = value_description jobtype.classname = value_classname jobtype.code = value_code jobtype.mode = JobTypeLoadMode.DOWNLOAD db.session.add(jobtype) with self.assertRaises(SyntaxError): db.session.commit()
def schema(): """ Returns the basic schema of :class:`.JobType` .. http:get:: /api/v1/jobtypes/schema HTTP/1.1 **Request** .. sourcecode:: http GET /api/v1/jobtypes/schema HTTP/1.1 Accept: application/json **Response** .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json { "batch_contiguous": "BOOLEAN", "classname": "VARCHAR(64)", "code": "TEXT", "description": "TEXT", "id": "INTEGER", "version": "INTEGER", "max_batch": "INTEGER", "no_automatic_start_time": "INTEGER", "name": "VARCHAR(64)" } :statuscode 200: no error """ schema_dict = JobTypeVersion.to_schema() schema_dict.update(JobType.to_schema()) return jsonify(schema_dict), OK
def post(self): """ A ``POST`` to this endpoint will create a new jobtype. .. http:post:: /api/v1/jobtypes/ HTTP/1.1 **Request** .. sourcecode:: http POST /api/v1/jobtypes/ HTTP/1.1 Accept: application/json { "name": "TestJobType", "classname": "TestJobType", "description": "Jobtype for testing inserts and queries", "code": "\\nfrom pyfarm.jobtypes.core.jobtype import " "JobType\\n\\nclass TestJobType(JobType):\\n" " def get_command(self):\\n" " return \"/usr/bin/touch\"\\n\\n" " def get_arguments(self):\\n" " return [os.path.join(" "self.assignment_data[\"job\"][\"data\"][\"path\"], " "\"%04d\" % self.assignment_data[\"tasks\"]" "[0][\"frame\"])]\\n" } **Response** .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json { "id": 1, "batch_contiguous": true, "software_requirements": [], "version": 1, "max_batch": 1, "name": "TestJobType", "classname": "TestJobType", "description": "Jobtype for testing inserts and queries", "code": "\\nfrom pyfarm.jobtypes.core.jobtype import " "JobType\\n\\nclass TestJobType(JobType):\\n" " def get_command(self):\\n" " return \"/usr/bin/touch\"\\n\\n" " def get_arguments(self):\\n" " return [os.path.join(" "self.assignment_data[\"job\"][\"data\"][\"path\"], " "\"%04d\" % self.assignment_data[\"tasks\"]" "[0][\"frame\"])]\\n" } :statuscode 201: a new jobtype item was created :statuscode 400: there was something wrong with the request (such as invalid columns being included) :statuscode 409: a conflicting jobtype already exists """ if "name" not in g.json: return jsonify( error="Jobtype does not specify a name"), BAD_REQUEST jobtype = JobType.query.filter_by(name=g.json["name"]).first() if jobtype: return (jsonify(error="Jobtype %s already exixts" % g.json["name"]), CONFLICT) try: jobtype = JobType() jobtype.name = g.json.pop("name") jobtype.description = g.json.pop("description", None) jobtype_version = JobTypeVersion() jobtype_version.jobtype = jobtype jobtype_version.version = 1 jobtype_version.code = g.json.pop("code") jobtype_version.classname = g.json.pop("classname", None) jobtype_version.batch_contiguous = g.json.pop( "batch_contiguous", None) jobtype_version.no_automatic_start_time = g.json.pop( "no_automatic_start_time", None) if "max_batch" in g.json and g.json["max_batch"] is None: g.json.pop("max_batch") jobtype_version.max_batch = sql.null() else: jobtype_version.max_batch = g.json.pop("max_batch", None) except KeyError as e: return (jsonify(error="Missing key in input: %r" % e.args), BAD_REQUEST) if "software_requirements" in g.json: try: for r in parse_requirements(g.json["software_requirements"]): r.jobtype_version = jobtype_version db.session.add(r) except (TypeError, ValueError) as e: return jsonify(error=e.args), BAD_REQUEST except ObjectNotFound as e: return jsonify(error=e.args), NOT_FOUND del g.json["software_requirements"] if g.json: return (jsonify(error="Unexpected keys in input: %r" % g.json.keys()), BAD_REQUEST) db.session.add_all([jobtype, jobtype_version]) db.session.commit() jobtype_data = jobtype_version.to_dict(unpack_relationships=False) jobtype_data.update( jobtype.to_dict(unpack_relationships=["software_requirements"])) del jobtype_data["jobtype_id"] logger.info("created jobtype %s: %r", jobtype.name, jobtype_data) return jsonify(jobtype_data), CREATED
def create_jobtype(): if request.method == "GET": return render_template("pyfarm/user_interface/jobtype_create.html", jobtypes=JobType.query, software_items=Software.query) else: with db.session.no_autoflush: jobtype = JobType() jobtype.name = request.form["name"] jobtype.description = request.form["description"] jobtype_version = JobTypeVersion() jobtype_version.jobtype = jobtype jobtype_version.version = 1 jobtype_version.max_batch = request.form["max_batch"].strip() or\ sql.null() jobtype_version.batch_contiguous =\ ("batch_contiguous" in request.form and request.form["batch_contiguous"] == "true") jobtype_version.no_automatic_start_time =\ ("no_automatic_start_time" in request.form and request.form["no_automatic_start_time"] == "true") jobtype_version.classname = request.form["classname"] jobtype_version.code = request.form["code"] requirements = zip(request.form.getlist("software"), request.form.getlist("min_version"), request.form.getlist("min_version")) for requirement_tuple in requirements: software = Software.query.filter_by( id=int(requirement_tuple[0])).first() if not software: return (render_template( "pyfarm/error.html", error="Software %s not found" % requirement_tuple[0]), NOT_FOUND) requirement = JobTypeSoftwareRequirement() requirement.software = software requirement.jobtype_version = jobtype_version if requirement_tuple[1] != "": minimum_version = SoftwareVersion.query.filter_by( id=int(requirement_tuple[1])).first() if not minimum_version: return (render_template( "pyfarm/error.html", error="Software version %s not " "found" % requirement_tuple[1]), NOT_FOUND) if minimum_version.software != software: return (render_template( "pyfarm/error.html", error="Software version %s " "does not belong to software %s" % (minimum_version.version, software.software)), BAD_REQUEST) requirement.min_version = minimum_version if requirement_tuple[2] != "": maximum_version = SoftwareVersion.query.filter_by( id=int(requirement_tuple[2])).first() if not maximum_version: return (render_template( "pyfarm/error.html", error="Software version %s not " "found" % requirement_tuple[2]), NOT_FOUND) if maximum_version.software != software: return (render_template( "pyfarm/error.html", error="Software version %s " "does not belong to software %s" % (maximum_version.version, software.software)), BAD_REQUEST) requirement.max_version = maximum_version db.session.add(requirement) db.session.add(jobtype) db.session.add(jobtype_version) db.session.commit() flash("Jobtype %s created" % jobtype.name) return redirect(url_for('jobtypes_index_ui'), SEE_OTHER)
def put(self, jobtype_name): """ A ``PUT`` to this endpoint will create a new jobtype under the given URI. If a jobtype already exists under that URI, a new version will be created with the given data. You should only call this by id for updating an existing jobtype or if you have a reserved jobtype id. There is currently no way to reserve a jobtype id. .. http:put:: /api/v1/jobtypes/[<str:name>|<int:id>] HTTP/1.1 **Request** .. sourcecode:: http PUT /api/v1/jobtypes/TestJobType HTTP/1.1 Accept: application/json { "name": "TestJobType", "description": "Jobtype for testing inserts and queries", "code": "\\nfrom pyfarm.jobtypes.core.jobtype import " "JobType\\n\\nclass TestJobType(JobType):\\n" " def get_command(self):\\n" " return \"/usr/bin/touch\"\\n\\n" " def get_arguments(self):\\n" " return [os.path.join(" "self.assignment_data[\"job\"][\"data\"][\"path\"], " "\"%04d\" % self.assignment_data[\"tasks\"]" "[0][\"frame\"])]\\n" } **Response** .. sourcecode:: http HTTP/1.1 201 CREATED Content-Type: application/json { "batch_contiguous": true, "classname": null, "code": "\\nfrom pyfarm.jobtypes.core.jobtype import " "JobType\\n\\nclass TestJobType(JobType):\\n" " def get_command(self):\\n" " return \"/usr/bin/touch\"\\n\\n" " def get_arguments(self):\\n" " return [os.path.join(" "self.assignment_data[\"job\"][\"data\"][\"path\"], " "\"%04d\" % self.assignment_data[\"tasks\"]" "[0][\"frame\"])]\\n", "id": 1, "max_batch": 1, "name": "TestJobType", "description": "Jobtype for testing inserts and queries", "software_requirements": [] } :statuscode 201: a new jobtype was created :statuscode 400: there was something wrong with the request (such as invalid columns being included) """ if isinstance(jobtype_name, STRING_TYPES): jobtype = JobType.query.filter(JobType.name == jobtype_name).first() else: jobtype = JobType.query.filter_by(id=jobtype_name).first() max_version = None new = False if jobtype else True if jobtype: logger.debug("jobtype %s will get a new version with data %r on commit", jobtype.name, g.json) max_version, = db.session.query(func.max(JobTypeVersion.version)).filter_by(jobtype=jobtype).first() else: jobtype = JobType() if max_version is not None: version = max_version + 1 else: version = 1 try: jobtype.name = g.json.pop("name") jobtype.description = g.json.pop("description", None) jobtype_version = JobTypeVersion() jobtype_version.jobtype = jobtype jobtype_version.version = version jobtype_version.code = g.json.pop("code") jobtype_version.classname = g.json.pop("classname", None) jobtype_version.batch_contiguous = g.json.pop("batch_contiguous", None) jobtype_version.no_automatic_start_time = g.json.pop("no_automatic_start_time", None) if "max_batch" in g.json and g.json["max_batch"] is None: g.json.pop("max_batch") jobtype_version.max_batch = sql.null() else: jobtype_version.max_batch = g.json.pop("max_batch", None) except KeyError as e: return (jsonify(error="Missing key in input: %r" % e.args), BAD_REQUEST) if "software_requirements" in g.json: try: for r in parse_requirements(g.json["software_requirements"]): r.jobtype_version = jobtype_version db.session.add(r) except (TypeError, ValueError) as e: return jsonify(error=e.args), BAD_REQUEST except ObjectNotFound as e: return jsonify(error=e.args), NOT_FOUND del g.json["software_requirements"] elif not new: # If the user did not specify a list of software requirements and # this jobtype is not new, retain the requirements from the previous # version previous_version = ( JobTypeVersion.query.filter(JobTypeVersion.jobtype == jobtype, JobTypeVersion.version != version) .order_by("version desc") .first() ) if previous_version: for old_req in previous_version.software_requirements: new_req = JobTypeSoftwareRequirement() new_req.jobtype_version = jobtype_version new_req.software_id = old_req.software_id new_req.min_version_id = old_req.min_version_id new_req.max_version_id = old_req.max_version_id db.session.add(new_req) if g.json: return (jsonify(error="Unexpected keys in input: %s" % g.json.keys()), BAD_REQUEST) db.session.add_all([jobtype, jobtype_version]) db.session.commit() jobtype_data = jobtype_version.to_dict(unpack_relationships=["software_requirements"]) jobtype_data.update(jobtype.to_dict(unpack_relationships=False)) del jobtype_data["jobtype_id"] logger.info("%s jobtype %s in put: %r", "created" if new else "updated", jobtype.name, jobtype_data) return jsonify(jobtype_data), CREATED
def produce_jobtype(self): rnd_text = lambda: hexlify(urandom(4)).decode("utf-8") jobtype = JobType(name=rnd_text(), description=rnd_text()) return jobtype
def test_validate_mode(self): jobtype = JobType() with self.assertRaises(ValueError): jobtype.mode = -1
def create_jobtype(): if request.method == "GET": return render_template("pyfarm/user_interface/jobtype_create.html", jobtypes=JobType.query, software_items=Software.query) else: with db.session.no_autoflush: jobtype = JobType() jobtype.name = request.form["name"] jobtype.description = request.form["description"] jobtype_version = JobTypeVersion() jobtype_version.jobtype = jobtype jobtype_version.version = 1 jobtype_version.max_batch = request.form["max_batch"].strip() or\ sql.null() jobtype_version.batch_contiguous =\ ("batch_contiguous" in request.form and request.form["batch_contiguous"] == "true") jobtype_version.no_automatic_start_time =\ ("no_automatic_start_time" in request.form and request.form["no_automatic_start_time"] == "true") jobtype_version.classname = request.form["classname"] jobtype_version.code = request.form["code"] requirements = zip(request.form.getlist("software"), request.form.getlist("min_version"), request.form.getlist("min_version")) for requirement_tuple in requirements: software = Software.query.filter_by( id=int(requirement_tuple[0])).first() if not software: return (render_template("pyfarm/error.html", error="Software %s not found" % requirement_tuple[0]), NOT_FOUND) requirement = JobTypeSoftwareRequirement() requirement.software = software requirement.jobtype_version = jobtype_version if requirement_tuple[1] != "": minimum_version = SoftwareVersion.query.filter_by( id=int(requirement_tuple[1])).first() if not minimum_version: return (render_template( "pyfarm/error.html", error="Software version %s not " "found" % requirement_tuple[1]), NOT_FOUND) if minimum_version.software != software: return (render_template( "pyfarm/error.html", error="Software version %s " "does not belong to software %s" % (minimum_version.version, software.software)), BAD_REQUEST) requirement.min_version = minimum_version if requirement_tuple[2] != "": maximum_version = SoftwareVersion.query.filter_by( id=int(requirement_tuple[2])).first() if not maximum_version: return (render_template( "pyfarm/error.html", error="Software version %s not " "found" % requirement_tuple[2]), NOT_FOUND) if maximum_version.software != software: return (render_template( "pyfarm/error.html", error="Software version %s " "does not belong to software %s" % (maximum_version.version, software.software)), BAD_REQUEST) requirement.max_version = maximum_version db.session.add(requirement) db.session.add(jobtype) db.session.add(jobtype_version) db.session.commit() flash("Jobtype %s created" % jobtype.name) return redirect(url_for('jobtypes_index_ui'), SEE_OTHER)
def put(self, jobtype_name): """ A ``PUT`` to this endpoint will create a new jobtype under the given URI. If a jobtype already exists under that URI, a new version will be created with the given data. You should only call this by id for updating an existing jobtype or if you have a reserved jobtype id. There is currently no way to reserve a jobtype id. .. http:put:: /api/v1/jobtypes/[<str:name>|<int:id>] HTTP/1.1 **Request** .. sourcecode:: http PUT /api/v1/jobtypes/TestJobType HTTP/1.1 Accept: application/json { "name": "TestJobType", "description": "Jobtype for testing inserts and queries", "code": "\\nfrom pyfarm.jobtypes.core.jobtype import " "JobType\\n\\nclass TestJobType(JobType):\\n" " def get_command(self):\\n" " return \"/usr/bin/touch\"\\n\\n" " def get_arguments(self):\\n" " return [os.path.join(" "self.assignment_data[\"job\"][\"data\"][\"path\"], " "\"%04d\" % self.assignment_data[\"tasks\"]" "[0][\"frame\"])]\\n" } **Response** .. sourcecode:: http HTTP/1.1 201 CREATED Content-Type: application/json { "batch_contiguous": true, "classname": null, "code": "\\nfrom pyfarm.jobtypes.core.jobtype import " "JobType\\n\\nclass TestJobType(JobType):\\n" " def get_command(self):\\n" " return \"/usr/bin/touch\"\\n\\n" " def get_arguments(self):\\n" " return [os.path.join(" "self.assignment_data[\"job\"][\"data\"][\"path\"], " "\"%04d\" % self.assignment_data[\"tasks\"]" "[0][\"frame\"])]\\n", "id": 1, "max_batch": 1, "name": "TestJobType", "description": "Jobtype for testing inserts and queries", "software_requirements": [] } :statuscode 201: a new jobtype was created :statuscode 400: there was something wrong with the request (such as invalid columns being included) """ if isinstance(jobtype_name, STRING_TYPES): jobtype = JobType.query.filter( JobType.name == jobtype_name).first() else: jobtype = JobType.query.filter_by(id=jobtype_name).first() max_version = None new = False if jobtype else True if jobtype: logger.debug( "jobtype %s will get a new version with data %r on commit", jobtype.name, g.json) max_version, = db.session.query(func.max( JobTypeVersion.version)).filter_by(jobtype=jobtype).first() else: jobtype = JobType() if max_version is not None: version = max_version + 1 else: version = 1 try: jobtype.name = g.json.pop("name") jobtype.description = g.json.pop("description", None) jobtype_version = JobTypeVersion() jobtype_version.jobtype = jobtype jobtype_version.version = version jobtype_version.code = g.json.pop("code") jobtype_version.classname = g.json.pop("classname", None) jobtype_version.batch_contiguous = g.json.pop( "batch_contiguous", None) jobtype_version.no_automatic_start_time =\ g.json.pop("no_automatic_start_time", None) if "max_batch" in g.json and g.json["max_batch"] is None: g.json.pop("max_batch") jobtype_version.max_batch = sql.null() else: jobtype_version.max_batch = g.json.pop("max_batch", None) except KeyError as e: return (jsonify(error="Missing key in input: %r" % e.args), BAD_REQUEST) if "software_requirements" in g.json: try: for r in parse_requirements(g.json["software_requirements"]): r.jobtype_version = jobtype_version db.session.add(r) except (TypeError, ValueError) as e: return jsonify(error=e.args), BAD_REQUEST except ObjectNotFound as e: return jsonify(error=e.args), NOT_FOUND del g.json["software_requirements"] elif not new: # If the user did not specify a list of software requirements and # this jobtype is not new, retain the requirements from the previous # version previous_version = JobTypeVersion.query.filter( JobTypeVersion.jobtype == jobtype, JobTypeVersion.version != version).order_by("version desc").first() if previous_version: for old_req in previous_version.software_requirements: new_req = JobTypeSoftwareRequirement() new_req.jobtype_version = jobtype_version new_req.software_id = old_req.software_id new_req.min_version_id = old_req.min_version_id new_req.max_version_id = old_req.max_version_id db.session.add(new_req) if g.json: return (jsonify(error="Unexpected keys in input: %s" % g.json.keys()), BAD_REQUEST) db.session.add_all([jobtype, jobtype_version]) db.session.commit() jobtype_data = jobtype_version.to_dict( unpack_relationships=["software_requirements"]) jobtype_data.update(jobtype.to_dict(unpack_relationships=False)) del jobtype_data["jobtype_id"] logger.info("%s jobtype %s in put: %r", "created" if new else "updated", jobtype.name, jobtype_data) return jsonify(jobtype_data), CREATED
def post(self): """ A ``POST`` to this endpoint will create a new jobtype. .. http:post:: /api/v1/jobtypes/ HTTP/1.1 **Request** .. sourcecode:: http POST /api/v1/jobtypes/ HTTP/1.1 Accept: application/json { "name": "TestJobType", "classname": "TestJobType", "description": "Jobtype for testing inserts and queries", "code": "\\nfrom pyfarm.jobtypes.core.jobtype import " "JobType\\n\\nclass TestJobType(JobType):\\n" " def get_command(self):\\n" " return \"/usr/bin/touch\"\\n\\n" " def get_arguments(self):\\n" " return [os.path.join(" "self.assignment_data[\"job\"][\"data\"][\"path\"], " "\"%04d\" % self.assignment_data[\"tasks\"]" "[0][\"frame\"])]\\n" } **Response** .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json { "id": 1, "batch_contiguous": true, "software_requirements": [], "version": 1, "max_batch": 1, "name": "TestJobType", "classname": "TestJobType", "description": "Jobtype for testing inserts and queries", "code": "\\nfrom pyfarm.jobtypes.core.jobtype import " "JobType\\n\\nclass TestJobType(JobType):\\n" " def get_command(self):\\n" " return \"/usr/bin/touch\"\\n\\n" " def get_arguments(self):\\n" " return [os.path.join(" "self.assignment_data[\"job\"][\"data\"][\"path\"], " "\"%04d\" % self.assignment_data[\"tasks\"]" "[0][\"frame\"])]\\n" } :statuscode 201: a new jobtype item was created :statuscode 400: there was something wrong with the request (such as invalid columns being included) :statuscode 409: a conflicting jobtype already exists """ if "name" not in g.json: return jsonify(error="Jobtype does not specify a name"), BAD_REQUEST jobtype = JobType.query.filter_by(name=g.json["name"]).first() if jobtype: return (jsonify(error="Jobtype %s already exixts" % g.json["name"]), CONFLICT) try: jobtype = JobType() jobtype.name = g.json.pop("name") jobtype.description = g.json.pop("description", None) jobtype_version = JobTypeVersion() jobtype_version.jobtype = jobtype jobtype_version.version = 1 jobtype_version.code = g.json.pop("code") jobtype_version.classname = g.json.pop("classname", None) jobtype_version.batch_contiguous = g.json.pop("batch_contiguous", None) jobtype_version.no_automatic_start_time = g.json.pop("no_automatic_start_time", None) if "max_batch" in g.json and g.json["max_batch"] is None: g.json.pop("max_batch") jobtype_version.max_batch = sql.null() else: jobtype_version.max_batch = g.json.pop("max_batch", None) except KeyError as e: return (jsonify(error="Missing key in input: %r" % e.args), BAD_REQUEST) if "software_requirements" in g.json: try: for r in parse_requirements(g.json["software_requirements"]): r.jobtype_version = jobtype_version db.session.add(r) except (TypeError, ValueError) as e: return jsonify(error=e.args), BAD_REQUEST except ObjectNotFound as e: return jsonify(error=e.args), NOT_FOUND del g.json["software_requirements"] if g.json: return (jsonify(error="Unexpected keys in input: %r" % g.json.keys()), BAD_REQUEST) db.session.add_all([jobtype, jobtype_version]) db.session.commit() jobtype_data = jobtype_version.to_dict(unpack_relationships=False) jobtype_data.update(jobtype.to_dict(unpack_relationships=["software_requirements"])) del jobtype_data["jobtype_id"] logger.info("created jobtype %s: %r", jobtype.name, jobtype_data) return jsonify(jobtype_data), CREATED