Verified Commit 1fcd64b9 authored by Peter Stanko's avatar Peter Stanko
Browse files

Submission has been extended - points and result field

parent c0a95638
"""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 ###
import json
import random import random
from pathlib import Path from pathlib import Path
from typing import Optional from typing import Optional
from storage import UploadedEntity from storage import UploadedEntity, entities
import portal.tools.worker_client import portal.tools.worker_client
from portal import logger, tools from portal import logger, tools
...@@ -136,3 +137,23 @@ class SubmissionProcessor: ...@@ -136,3 +137,23 @@ class SubmissionProcessor:
def _worker_not_available(self): def _worker_not_available(self):
log.warning(f"[PROC] Worker is no available for submission: {self.submission.log_name}") 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
...@@ -31,6 +31,8 @@ def upload_results_to_storage(new_submission_id: str, path: str): ...@@ -31,6 +31,8 @@ def upload_results_to_storage(new_submission_id: str, path: str):
processor = submission_processor.SubmissionProcessor(new_submission) processor = submission_processor.SubmissionProcessor(new_submission)
file_params = dict(source=dict(url=path, type='zip')) file_params = dict(source=dict(url=path, type='zip'))
processor.upload_result(path=path, file_params=file_params) 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') @celery_app.task(name='clone-submission-files')
......
...@@ -914,6 +914,8 @@ class Submission(db.Model, EntityBase): ...@@ -914,6 +914,8 @@ class Submission(db.Model, EntityBase):
passive_deletes=True, uselist=False) passive_deletes=True, uselist=False)
async_task_id = db.Column(db.String(length=36)) 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') course = association_proxy('project', 'course')
@property @property
......
...@@ -22,7 +22,8 @@ class NestedCollection: ...@@ -22,7 +22,8 @@ class NestedCollection:
'Submission': ('id', 'state', 'user.id', 'user.username', 'Submission': ('id', 'state', 'user.id', 'user.username',
'project.id', 'project.codename', 'project.id', 'project.codename',
'course.id', 'course.codename', 'course.id', 'course.codename',
'created_at', 'updated_at'), 'created_at', 'updated_at',
'result', 'points'),
'ReviewItem': ('id', 'review.id', 'line', 'content', 'file', 'user.id'), 'ReviewItem': ('id', 'review.id', 'line', 'content', 'file', 'user.id'),
'Secret': ('id', 'name', 'expires_at') 'Secret': ('id', 'name', 'expires_at')
} }
...@@ -267,6 +268,8 @@ class SubmissionSchema(BaseSchema, Schema): ...@@ -267,6 +268,8 @@ class SubmissionSchema(BaseSchema, Schema):
project = NESTED['project'] project = NESTED['project']
course = NESTED['course'] course = NESTED['course']
user = NESTED['user'] user = NESTED['user']
points = fields.Number()
result = fields.Str(allow_none=True)
class ReviewSchema(BaseSchema, Schema): class ReviewSchema(BaseSchema, Schema):
...@@ -383,7 +386,8 @@ class Schemas: ...@@ -383,7 +386,8 @@ class Schemas:
'user_reduced': (*ALWAYS_ALLOWED, 'username', 'uco', 'email', 'name'), 'user_reduced': (*ALWAYS_ALLOWED, 'username', 'uco', 'email', 'name'),
'users': (*ALWAYS_ALLOWED, 'username', 'uco', 'email'), 'users': (*ALWAYS_ALLOWED, 'username', 'uco', 'email'),
'clients': (*ALWAYS_ALLOWED, 'codename', 'type'), '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'), 'submission_state': (*ALWAYS_ALLOWED, 'state', 'parameters', 'scheduled_for'),
'roles': ENT_W_COURSE, 'roles': ENT_W_COURSE,
'groups': ENT_W_COURSE, 'groups': ENT_W_COURSE,
...@@ -393,8 +397,8 @@ class Schemas: ...@@ -393,8 +397,8 @@ class Schemas:
'config_reduced': (*ALWAYS_ALLOWED, 'project', 'submissions_allowed_from', 'config_reduced': (*ALWAYS_ALLOWED, 'project', 'submissions_allowed_from',
'submissions_allowed_to', 'file_whitelist'), 'submissions_allowed_to', 'file_whitelist'),
'secrets': ( 'secrets': (
*ALWAYS_ALLOWED, 'name', 'expires_at', 'client.id', 'client.type', 'client.name', *ALWAYS_ALLOWED, 'name', 'expires_at', 'client.id', 'client.type', 'client.name',
'client.codename'), 'client.codename'),
'secret': (*ALWAYS_ALLOWED, 'name', 'expires_at', 'client.id', 'client.type', 'client.name', 'secret': (*ALWAYS_ALLOWED, 'name', 'expires_at', 'client.id', 'client.type', 'client.name',
'client.codename') 'client.codename')
} }
......
...@@ -155,3 +155,8 @@ class SubmissionDiffTimeError(PortalAPIError): ...@@ -155,3 +155,8 @@ class SubmissionDiffTimeError(PortalAPIError):
f"you can create submission in {diff_time}." f"you can create submission in {diff_time}."
super().__init__(code=429, message=message) super().__init__(code=429, message=message)
class SuiteStatsNotExists(PortalError):
def __init__(self, submission):
self.message = f"Suite stats have not been found for the submission: {submission.log_name}"
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment