datatracker/ietf/submit/models.py
Henrik Levkowetz d98054c103 Added a new yang checker, 'yanglint', to the existing Yang checker class, in
addition to the existing 'pyang' checker.

Added modal overlay displays showing the yang check results every place the
yin/yang symbol is shown (red or green) to indicate the presencee and result
of yang checks.  Added a Yang Validation: line in the document
meta-information section on the document's page in the datatracker.

Added the result of the xym extaction to the yang check results, to make
extration failures visible.

Added the version of the used xym, pyang, and yanglint commands to the check
results.

Added an action to move successfully extracted and validated modules to the
module library directories immediately on submission.

Added the xym and pyang repositories as svn:external components, rather than
listing them in requirements.txt, as there has been delays of many months
between essential features in the repositories, and an actual release.  We may
get occasional buildbot failures if broken code is pulled in from the
repository, but better that than the functionality failure of severely
outdated componets.

Added a new management command to re-run yang validation for active drafts for
which yang modules were found at submission time, in order to pick up imported
models which may have arrived in the model libraries after the draft's
submission.  Run daily from bin/daily.

Added a table to hold version information for external commands.  The yang
checker output should include the version information of the used checkers,
but seems unnecessary to run each command with its --version switch every
time we check a module...

Added a new management command to collect version information for external
commands on demand.  To be run daily from bin/daily.

Added tests to verify that xym, pyang and yanglint information is available
on the submission confirmation page, and updated the yang module contained in
the test document to validate under both pyang and yanglint.

Updated admin.py and resource.py files as needed.
 - Legacy-Id: 13630
2017-06-15 16:09:28 +00:00

123 lines
4.8 KiB
Python

import datetime
import email
from django.db import models
import jsonfield
import debug # pyflakes:ignore
from ietf.doc.models import Document
from ietf.person.models import Person
from ietf.group.models import Group
from ietf.message.models import Message
from ietf.name.models import DraftSubmissionStateName, FormalLanguageName
from ietf.utils.accesstoken import generate_random_key, generate_access_token
def parse_email_line(line):
"""
Split email address into name and email like
email.utils.parseaddr() but return a dictionary
"""
name, addr = email.utils.parseaddr(line) if '@' in line else (line, '')
return dict(name=name, email=addr)
class Submission(models.Model):
state = models.ForeignKey(DraftSubmissionStateName)
remote_ip = models.CharField(max_length=100, blank=True)
access_key = models.CharField(max_length=255, default=generate_random_key)
auth_key = models.CharField(max_length=255, blank=True)
# draft metadata
name = models.CharField(max_length=255, db_index=True)
group = models.ForeignKey(Group, null=True, blank=True)
title = models.CharField(max_length=255, blank=True)
abstract = models.TextField(blank=True)
rev = models.CharField(max_length=3, blank=True)
pages = models.IntegerField(null=True, blank=True)
words = models.IntegerField(null=True, blank=True)
formal_languages = models.ManyToManyField(FormalLanguageName, blank=True, help_text="Formal languages used in document")
authors = jsonfield.JSONField(default=list, help_text="List of authors with name, email, affiliation and country.")
note = models.TextField(blank=True)
replaces = models.CharField(max_length=1000, blank=True)
first_two_pages = models.TextField(blank=True)
file_types = models.CharField(max_length=50, blank=True)
file_size = models.IntegerField(null=True, blank=True)
document_date = models.DateField(null=True, blank=True)
submission_date = models.DateField(default=datetime.date.today)
submitter = models.CharField(max_length=255, blank=True, help_text="Name and email of submitter, e.g. \"John Doe <john@example.org>\".")
draft = models.ForeignKey(Document, null=True, blank=True)
def __unicode__(self):
return u"%s-%s" % (self.name, self.rev)
def submitter_parsed(self):
return parse_email_line(self.submitter)
def access_token(self):
return generate_access_token(self.access_key)
def existing_document(self):
return Document.objects.filter(name=self.name).first()
def latest_checks(self):
checks = [ self.checks.filter(checker=c, passed__in=[True,False]).latest('time') for c in self.checks.values_list('checker', flat=True).distinct() ]
return checks
class SubmissionCheck(models.Model):
time = models.DateTimeField(auto_now=True)
submission = models.ForeignKey(Submission, related_name='checks')
checker = models.CharField(max_length=256, blank=True)
passed = models.NullBooleanField(default=False)
message = models.TextField(null=True, blank=True)
errors = models.IntegerField(null=True, blank=True, default=None)
warnings = models.IntegerField(null=True, blank=True, default=None)
items = jsonfield.JSONField(null=True, blank=True, default='{}')
symbol = models.CharField(max_length=64, default='')
#
def __unicode__(self):
return "%s submission check: %s: %s" % (self.checker, 'Passed' if self.passed else 'Failed', self.message[:48]+'...')
def has_warnings(self):
return self.warnings != '[]'
def has_errors(self):
return self.errors != '[]'
class SubmissionEvent(models.Model):
submission = models.ForeignKey(Submission)
time = models.DateTimeField(default=datetime.datetime.now)
by = models.ForeignKey(Person, null=True, blank=True)
desc = models.TextField()
def __unicode__(self):
return u"%s %s by %s at %s" % (self.submission.name, self.desc, self.by.plain_name() if self.by else "(unknown)", self.time)
class Meta:
ordering = ("-time", "-id")
class Preapproval(models.Model):
"""Pre-approved draft submission name."""
name = models.CharField(max_length=255, db_index=True)
by = models.ForeignKey(Person)
time = models.DateTimeField(default=datetime.datetime.now)
def __unicode__(self):
return self.name
class SubmissionEmailEvent(SubmissionEvent):
message = models.ForeignKey(Message, null=True, blank=True,related_name='manualevents')
msgtype = models.CharField(max_length=25)
in_reply_to = models.ForeignKey(Message, null=True, blank=True,related_name='irtomanual')
def __unicode__(self):
return u"%s %s by %s at %s" % (self.submission.name, self.desc, self.by.plain_name() if self.by else "(unknown)", self.time)
class Meta:
ordering = ['-time', '-id']