Loading migrations/versions/cdb5d9fc0f2c_.py 0 → 100644 +30 −0 Original line number Diff line number Diff line """empty message Revision ID: cdb5d9fc0f2c Revises: 0d5113dee43f Create Date: 2018-10-08 20:33:57.225008 """ from alembic import op import sqlalchemy as sa # revision identifiers, used by Alembic. revision = 'cdb5d9fc0f2c' down_revision = '0d5113dee43f' branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.add_column('submission', sa.Column('points', sa.Numeric(precision=4), nullable=True)) op.add_column('submission', sa.Column('result', sa.String(length=10), nullable=True)) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### op.drop_column('submission', 'result') op.drop_column('submission', 'points') # ### end Alembic commands ### portal/async_celery/submission_processor.py +22 −1 Original line number Diff line number Diff line import json import random from pathlib import Path from typing import Optional from storage import UploadedEntity from storage import UploadedEntity, entities import portal.tools.worker_client from portal import logger, tools Loading Loading @@ -136,3 +137,23 @@ class SubmissionProcessor: def _worker_not_available(self): log.warning(f"[PROC] Worker is no available for submission: {self.submission.log_name}") def process_result(self): storage_entity = self.storage.results.get(self.submission.id) # @mdujava - here put submission processing self._submission_result_processing(storage_entity) def _submission_result_processing(self, storage_entity: entities.Entity): suite_stats = storage_entity.get('suite-stats.json') if not suite_stats.exists(): log.error(f"[PROC] Suite stats for the {self.submission.log_name} have not been found.") raise errors.SuiteStatsNotExists(self.submission.id) stats = json.loads(suite_stats.read_text('utf-8')) return self._parse_stats(stats) def _parse_stats(self, stats: dict): points = stats.get('final_points', 0) result = stats.get('result', 'none').lower() self.submission.result = result self.submission.points = points return self.submission portal/async_celery/tasks.py +2 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,8 @@ def upload_results_to_storage(new_submission_id: str, path: str): processor = submission_processor.SubmissionProcessor(new_submission) file_params = dict(source=dict(url=path, type='zip')) processor.upload_result(path=path, file_params=file_params) submission = processor.process_result() rest_service.submissions.write_entity(submission) @celery_app.task(name='clone-submission-files') Loading portal/database/models.py +2 −0 Original line number Diff line number Diff line Loading @@ -914,6 +914,8 @@ class Submission(db.Model, EntityBase): passive_deletes=True, uselist=False) async_task_id = db.Column(db.String(length=36)) points = db.Column(db.Numeric(precision=4), default=0) result = db.Column(db.String(length=10), default='none') course = association_proxy('project', 'course') @property Loading portal/rest/schemas.py +8 −4 Original line number Diff line number Diff line Loading @@ -22,7 +22,8 @@ class NestedCollection: 'Submission': ('id', 'state', 'user.id', 'user.username', 'project.id', 'project.codename', 'course.id', 'course.codename', 'created_at', 'updated_at'), 'created_at', 'updated_at', 'result', 'points'), 'ReviewItem': ('id', 'review.id', 'line', 'content', 'file', 'user.id'), 'Secret': ('id', 'name', 'expires_at') } Loading Loading @@ -267,6 +268,8 @@ class SubmissionSchema(BaseSchema, Schema): project = NESTED['project'] course = NESTED['course'] user = NESTED['user'] points = fields.Number() result = fields.Str(allow_none=True) class ReviewSchema(BaseSchema, Schema): Loading Loading @@ -383,7 +386,8 @@ class Schemas: 'user_reduced': (*ALWAYS_ALLOWED, 'username', 'uco', 'email', 'name'), 'users': (*ALWAYS_ALLOWED, 'username', 'uco', 'email'), 'clients': (*ALWAYS_ALLOWED, 'codename', 'type'), 'submissions': (*ALWAYS_ALLOWED, 'course', 'state', 'project', 'scheduled_for', 'user'), 'submissions': (*ALWAYS_ALLOWED, 'course', 'state', 'project', 'scheduled_for', 'user', 'points', 'result'), 'submission_state': (*ALWAYS_ALLOWED, 'state', 'parameters', 'scheduled_for'), 'roles': ENT_W_COURSE, 'groups': ENT_W_COURSE, Loading @@ -393,8 +397,8 @@ class Schemas: 'config_reduced': (*ALWAYS_ALLOWED, 'project', 'submissions_allowed_from', 'submissions_allowed_to', 'file_whitelist'), 'secrets': ( *ALWAYS_ALLOWED, 'name', 'expires_at', 'client.id', 'client.type', 'client.name', 'client.codename'), *ALWAYS_ALLOWED, 'name', 'expires_at', 'client.id', 'client.type', 'client.name', 'client.codename'), 'secret': (*ALWAYS_ALLOWED, 'name', 'expires_at', 'client.id', 'client.type', 'client.name', 'client.codename') } Loading Loading
migrations/versions/cdb5d9fc0f2c_.py 0 → 100644 +30 −0 Original line number Diff line number Diff line """empty message Revision ID: cdb5d9fc0f2c Revises: 0d5113dee43f Create Date: 2018-10-08 20:33:57.225008 """ from alembic import op import sqlalchemy as sa # revision identifiers, used by Alembic. revision = 'cdb5d9fc0f2c' down_revision = '0d5113dee43f' branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.add_column('submission', sa.Column('points', sa.Numeric(precision=4), nullable=True)) op.add_column('submission', sa.Column('result', sa.String(length=10), nullable=True)) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### op.drop_column('submission', 'result') op.drop_column('submission', 'points') # ### end Alembic commands ###
portal/async_celery/submission_processor.py +22 −1 Original line number Diff line number Diff line import json import random from pathlib import Path from typing import Optional from storage import UploadedEntity from storage import UploadedEntity, entities import portal.tools.worker_client from portal import logger, tools Loading Loading @@ -136,3 +137,23 @@ class SubmissionProcessor: def _worker_not_available(self): log.warning(f"[PROC] Worker is no available for submission: {self.submission.log_name}") def process_result(self): storage_entity = self.storage.results.get(self.submission.id) # @mdujava - here put submission processing self._submission_result_processing(storage_entity) def _submission_result_processing(self, storage_entity: entities.Entity): suite_stats = storage_entity.get('suite-stats.json') if not suite_stats.exists(): log.error(f"[PROC] Suite stats for the {self.submission.log_name} have not been found.") raise errors.SuiteStatsNotExists(self.submission.id) stats = json.loads(suite_stats.read_text('utf-8')) return self._parse_stats(stats) def _parse_stats(self, stats: dict): points = stats.get('final_points', 0) result = stats.get('result', 'none').lower() self.submission.result = result self.submission.points = points return self.submission
portal/async_celery/tasks.py +2 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,8 @@ def upload_results_to_storage(new_submission_id: str, path: str): processor = submission_processor.SubmissionProcessor(new_submission) file_params = dict(source=dict(url=path, type='zip')) processor.upload_result(path=path, file_params=file_params) submission = processor.process_result() rest_service.submissions.write_entity(submission) @celery_app.task(name='clone-submission-files') Loading
portal/database/models.py +2 −0 Original line number Diff line number Diff line Loading @@ -914,6 +914,8 @@ class Submission(db.Model, EntityBase): passive_deletes=True, uselist=False) async_task_id = db.Column(db.String(length=36)) points = db.Column(db.Numeric(precision=4), default=0) result = db.Column(db.String(length=10), default='none') course = association_proxy('project', 'course') @property Loading
portal/rest/schemas.py +8 −4 Original line number Diff line number Diff line Loading @@ -22,7 +22,8 @@ class NestedCollection: 'Submission': ('id', 'state', 'user.id', 'user.username', 'project.id', 'project.codename', 'course.id', 'course.codename', 'created_at', 'updated_at'), 'created_at', 'updated_at', 'result', 'points'), 'ReviewItem': ('id', 'review.id', 'line', 'content', 'file', 'user.id'), 'Secret': ('id', 'name', 'expires_at') } Loading Loading @@ -267,6 +268,8 @@ class SubmissionSchema(BaseSchema, Schema): project = NESTED['project'] course = NESTED['course'] user = NESTED['user'] points = fields.Number() result = fields.Str(allow_none=True) class ReviewSchema(BaseSchema, Schema): Loading Loading @@ -383,7 +386,8 @@ class Schemas: 'user_reduced': (*ALWAYS_ALLOWED, 'username', 'uco', 'email', 'name'), 'users': (*ALWAYS_ALLOWED, 'username', 'uco', 'email'), 'clients': (*ALWAYS_ALLOWED, 'codename', 'type'), 'submissions': (*ALWAYS_ALLOWED, 'course', 'state', 'project', 'scheduled_for', 'user'), 'submissions': (*ALWAYS_ALLOWED, 'course', 'state', 'project', 'scheduled_for', 'user', 'points', 'result'), 'submission_state': (*ALWAYS_ALLOWED, 'state', 'parameters', 'scheduled_for'), 'roles': ENT_W_COURSE, 'groups': ENT_W_COURSE, Loading @@ -393,8 +397,8 @@ class Schemas: 'config_reduced': (*ALWAYS_ALLOWED, 'project', 'submissions_allowed_from', 'submissions_allowed_to', 'file_whitelist'), 'secrets': ( *ALWAYS_ALLOWED, 'name', 'expires_at', 'client.id', 'client.type', 'client.name', 'client.codename'), *ALWAYS_ALLOWED, 'name', 'expires_at', 'client.id', 'client.type', 'client.name', 'client.codename'), 'secret': (*ALWAYS_ALLOWED, 'name', 'expires_at', 'client.id', 'client.type', 'client.name', 'client.codename') } Loading