class TestJSONField(TestCase): def setUp(self): self.json_field = JSONField() self.obj = {'test': 12} self.obj_json = json.dumps(self.obj) def test_to_python(self): """Assert the value returned by to_python is the same as the initial value""" new_obj = self.json_field.to_python(self.obj_json) self.assertDictEqual(self.obj, new_obj) def test_from_db_value(self): """Assert the value returned by from_db_value is the same as the initial value""" new_obj = self.json_field.from_db_value(self.obj_json) self.assertDictEqual(self.obj, new_obj) def test_get_db_prep_value(self): """Assert the value returned by get_db_prep_value matches a serialized version of obj""" new_obj = self.json_field.get_db_prep_value(self.obj) self.assertEquals(self.obj_json, new_obj) def test_value_to_string(self): """Assert the value returned by value_to_string matches a json-serialized version of obj""" with patch('pulpcore.app.fields.JSONField.value_from_object', return_value=self.obj): new_obj = self.json_field.value_to_string(object()) self.assertEquals(self.obj_json, new_obj)
class Task(Model): """ Represents a task Fields: state (models.TextField): The state of the task started_at (models.DateTimeField): The time the task started executing finished_at (models.DateTimeField): The time the task finished executing non_fatal_errors (pulpcore.app.fields.JSONField): Dictionary of non-fatal errors that occurred while task was running. error (pulpcore.app.fields.JSONField): Fatal errors generated by the task Relations: parent (models.ForeignKey): Task that spawned this task (if any) worker (models.ForeignKey): The worker that this task is in """ id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) state = models.TextField(choices=TASK_CHOICES) started_at = models.DateTimeField(null=True) finished_at = models.DateTimeField(null=True) non_fatal_errors = JSONField(default=list) error = JSONField(null=True) parent = models.ForeignKey("Task", null=True, related_name="spawned_tasks", on_delete=models.SET_NULL) worker = models.ForeignKey("Worker", null=True, related_name="tasks", on_delete=models.SET_NULL) @staticmethod def current(): """ Returns: pulpcore.app.models.Task: The current task. """ try: task_id = get_current_job().id except AttributeError: task = None else: task = Task.objects.get(pk=task_id) return task def set_running(self): """ Set this Task to the running state, save it, and log output in warning cases. This updates the :attr:`started_at` and sets the :attr:`state` to :attr:`RUNNING`. """ if self.state != TASK_STATES.WAITING: _logger.warning(_('Task __call__() occurred but Task %s is not at WAITING') % self.id) self.state = TASK_STATES.RUNNING self.started_at = timezone.now() self.save() def set_completed(self): """ Set this Task to the completed state, save it, and log output in warning cases. This updates the :attr:`finished_at` and sets the :attr:`state` to :attr:`COMPLETED`. """ self.finished_at = timezone.now() # Only set the state to finished if it's not already in a complete state. This is # important for when the task has been canceled, so we don't move the task from canceled # to finished. if self.state not in TASK_FINAL_STATES: self.state = TASK_STATES.COMPLETED else: msg = _('Task set_completed() occurred but Task %s is already in final state') _logger.warning(msg % self.id) self.save() def set_failed(self, exc, tb): """ Set this Task to the failed state and save it. This updates the :attr:`finished_at` attribute, sets the :attr:`state` to :attr:`FAILED`, and sets the :attr:`error` attribute. Args: exc (Exception): The exception raised by the task. tb (traceback): Traceback instance for the current exception. """ self.state = TASK_STATES.FAILED self.finished_at = timezone.now() tb_str = ''.join(traceback.format_tb(tb)) self.error = exception_to_dict(exc, tb_str) self.save() def release_resources(self): """ Release the reserved resources that are reserved by this task. If a reserved resource no longer has any tasks reserving it, delete it. """ for reservation in self.reserved_resources.all(): TaskReservedResource.objects.filter(task=self.id).delete() if not reservation.tasks.exists(): reservation.delete()
def setUp(self): self.json_field = JSONField() self.obj = {'test': 12} self.obj_json = json.dumps(self.obj)