"""Markbox-specific routines for printing examinations.
Routines for generating the API request to Markbox and handling the
responses.
"""
import json
import urllib.request, urllib.error, urllib.parse
from ll.xist.ns import html
from uw.local.config import read_config
from .pdf import embed_fonts
api_key_config = read_config ()
[docs]def issue_create_request (cursor, exam, request_json, now):
request = urllib.request.Request (format_create_url ())
request.add_header ("Content-Type", "application/vnd.api+json")
request.data = (json.dumps (request_json).encode ())
request.add_header ("Authorization", "Token token=%s" % api_key_config.get ('markbox', 'request_token'))
try:
response = urllib.request.urlopen (request)
success = True
except urllib.error.HTTPError as x:
response = x
success = False
status = response.getcode ()
result = response.read ()
cursor.execute_none ("update markbox_create_request set response_status = %(status)s, response_body = %(response)s where request_time = %(time)s and response_status is null", status=status, response=result, time=now)
cursor.connection.commit ()
if success and status == 201:
# Success - record slug in
result_json = json.loads (result.decode ())
slug = str (result_json['slug'])
cursor.execute_none ("update markbox_exam set markbox_exam_code = %(code)s where exam_id = %(exam_id)s", exam_id=exam.exam_id, code=slug)
cursor.connection.commit ()
return slug
else:
print (result)
raise response
[docs]def create_exam (cursor, exam):
if not exam.scanning_integration == 'M':
raise ValueError ('Assessment not configured for Markbox')
now = cursor.execute_required_value ("insert into markbox_create_request (exam_id) values (%(exam_id)s) returning request_time", exam_id=exam.exam_id)
cursor.connection.commit ()
request_json = format_exam_json (cursor, exam)
cursor.execute_none ("update markbox_create_request set request_json = %(request_json)s where request_time = %(time)s and request_json is null", request_json=json.dumps (request_json), time=now)
cursor.connection.commit ()
slug = issue_create_request (cursor, exam, request_json, now)
return request_json, slug
[docs]def send_classlist (cursor, exam):
request_json = format_candidate_json (cursor, exam)
request = urllib.request.Request (format_classlist_url (exam))
request.add_header ("Content-Type", "application/vnd.api+json")
request.data = (json.dumps (request_json).encode ())
request.add_header ("Authorization", "Token token=%s" % api_key_config.get ('markbox', 'request_token'))
try:
response = urllib.request.urlopen (request)
success = True
except urllib.error.HTTPError as x:
response = x
success = False
status = response.getcode ()
result = response.read ()
if success:
return status, result
else:
print (result)
raise response
[docs]def markbox_process_pdf (cursor, exam_id):
"""Embed fonts in the Markbox PDF for the specified examination.
:param cursor: DB cursor.
:param exam_id: The exam_id of the examination to process.
Obtain the raw PDF from
markbox_exam.markbox_answer_page_pdf_raw, process it through the
standard font embedding process, and store the result in
markbox_exam.markbox_answer_page_pdf.
"""
pdf_raw, pdf_old = cursor.execute_required_tuple ("select markbox_answer_page_pdf_raw, markbox_answer_page_pdf from markbox_exam where exam_id = %(exam_id)s for no key update nowait", exam_id=exam_id)
if pdf_raw is None:
raise SystemError (["Raw PDF is NULL"])
if pdf_old is not None:
raise SystemError (["Old PDF is not NULL"])
status, result = embed_fonts (pdf_raw)
if not status:
raise SystemError (result)
cursor.execute_none ("update markbox_exam set markbox_answer_page_pdf = %(pdf)s where exam_id = %(exam_id)s", exam_id=exam_id, pdf=result)
cursor.connection.commit ()
[docs]def get_pdf (cursor, exam):
request = urllib.request.Request (format_pdf_url (exam))
request.add_header ("Authorization", "Token token=%s" % api_key_config.get ('markbox', 'request_token'))
try:
response = urllib.request.urlopen (request)
success = True
except urllib.error.HTTPError as x:
response = x
success = False
status = response.getcode ()
result = response.read ()
if success and status == 200:
cursor.execute_none ("update markbox_exam set markbox_answer_page_pdf_raw = %(pdf)s, markbox_answer_page_pdf = null where exam_id = %(exam_id)s", exam_id=exam.exam_id, pdf=result)
cursor.connection.commit ()
markbox_process_pdf (cursor, exam.exam_id)
else:
print (result)
raise response
[docs]def markbox_exam (cursor, exam):
create_exam (cursor, exam)
# Need to get the markbox slug for remaining steps
exam = cursor.exam_by_id (exam_id=exam.exam_id)
send_classlist (cursor, exam)
get_pdf (cursor, exam)