Message ID | 1444387202-25735-7-git-send-email-damien.lespiau@intel.com |
---|---|
State | Superseded |
Headers | show |
> v2: Add 'order' metadata to revisions as they do have a natural > ordering. > v3: Add a couple of utility functions to Series and SeriesRevision > v4: Provide a get_absolute_url() method on Series > v5: Add a dump() method to series, handy for debugging > > Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> Couple of comments below. Stephen > --- > patchwork/models.py | 83 > +++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 83 insertions(+) > > diff --git a/patchwork/models.py b/patchwork/models.py > index a1c2974..68673bf 100644 > --- a/patchwork/models.py > +++ b/patchwork/models.py > @@ -410,6 +410,89 @@ class BundlePatch(models.Model): > unique_together = [('bundle', 'patch')] > ordering = ['order'] > > +# This Model represents the "top level" Series, an object that doesn't > change > +# with the various versions of patches sent to the mailing list. This should be a docstring. > +class Series(models.Model): > + project = models.ForeignKey(Project) > + name = models.CharField(max_length=200, null=True, blank=False) > + submitter = models.ForeignKey(Person, related_name='submitters') > + reviewer = models.ForeignKey(User, related_name='reviewers', > null=True, > + blank=True) > + submitted = models.DateTimeField(default=datetime.datetime.now) Potential edge case: what happens if a series doesn't have a cover letter (and therefore no email to get the "submitted" time from)? > + last_updated = models.DateTimeField(auto_now=True) > + # Caches the latest version so we can display it without looking at > the max > + # of all SeriesRevision.version > + version = models.IntegerField(default=1) > + # This is the number of patches of the latest version. > + n_patches = models.IntegerField(default=0) > + > + def __unicode__(self): > + return self.name > + > + def revisions(self): > + return SeriesRevision.objects.filter(series=self) > + > + def latest_revision(self): > + return self.revisions().reverse()[0] return self.revisions[-1] > + > + def get_absolute_url(self): > + return reverse('series', kwargs={ 'series': self.pk }) > + > + def dump(self): > + print('') > + print('===') > + print('Series: %s' % self) > + print(' version %d' % self.version) > + for rev in self.revisions(): > + print(' rev %d:' % rev.version) > + i = 1 > + for patch in rev.ordered_patches(): > + print(' patch %d:' % i) > + print(' subject: %s' % patch.name) > + print(' msgid : %s' % patch.msgid) > + i += 1 No need reinventing the wheel: override the '__str__' (not the '__repr__') function instead > + > +# A 'revision' of a series. Resending a new version of a patch or a full > new > +# iteration of a series will create a new revision. Docstring > +class SeriesRevision(models.Model): > + series = models.ForeignKey(Series) > + version = models.IntegerField(default=1) > + root_msgid = models.CharField(max_length=255) > + cover_letter = models.TextField(null = True, blank = True) > + patches = models.ManyToManyField(Patch, through = > 'SeriesRevisionPatch') > + > + class Meta: > + unique_together = [('series', 'version')] > + ordering = ['version'] > + > + def ordered_patches(self): > + return self.patches.order_by('seriesrevisionpatch__order') > + > + def add_patch(self, patch, order): > + # see if the patch is already in this revision > + if SeriesRevisionPatch.objects.filter(revision=self, > + patch=patch).count(): > + raise Exception("patch is already in revision") > + > + sp = SeriesRevisionPatch.objects.create(revision=self, > patch=patch, > + order=order) > + sp.save() > + > + def __unicode__(self): > + if hasattr(self, 'series'): > + return self.series.name + " (rev " + str(self.version) + ")" > + else: > + return "New revision" + " (rev " + str(self.version) + ")" You could stick in the '@python_2_unicode_compatible' decorator on this function and use '__str__' instead - this would make this model Python 3 compatible. Up to you, however. > + > +class SeriesRevisionPatch(models.Model): > + patch = models.ForeignKey(Patch) > + revision = models.ForeignKey(SeriesRevision) > + order = models.IntegerField() > + > + class Meta: > + unique_together = [('revision', 'patch'), ('revision', 'order')] > + ordering = ['order'] > + > class EmailConfirmation(models.Model): > validity = datetime.timedelta(days = > settings.CONFIRMATION_VALIDITY_DAYS) > type = models.CharField(max_length = 20, choices = [ > -- > 2.1.0 > > _______________________________________________ > Patchwork mailing list > Patchwork@lists.ozlabs.org > https://lists.ozlabs.org/listinfo/patchwork
On Sat, Oct 10, 2015 at 12:21:15AM +0100, Finucane, Stephen wrote: > > +class Series(models.Model): > > + project = models.ForeignKey(Project) > > + name = models.CharField(max_length=200, null=True, blank=False) > > + submitter = models.ForeignKey(Person, related_name='submitters') > > + reviewer = models.ForeignKey(User, related_name='reviewers', > > null=True, > > + blank=True) > > + submitted = models.DateTimeField(default=datetime.datetime.now) > > Potential edge case: what happens if a series doesn't have a cover > letter (and therefore no email to get the "submitted" time from)? submitted is the timestamp of the row creation, disregarding if the series has a cover letter or not. No email is getting parsed to set that field. > > + last_updated = models.DateTimeField(auto_now=True) > > + # Caches the latest version so we can display it without looking at > > the max > > + # of all SeriesRevision.version > > + version = models.IntegerField(default=1) > > + # This is the number of patches of the latest version. > > + n_patches = models.IntegerField(default=0) > > + > > + def __unicode__(self): > > + return self.name > > + > > + def revisions(self): > > + return SeriesRevision.objects.filter(series=self) > > + > > + def latest_revision(self): > > + return self.revisions().reverse()[0] > > return self.revisions[-1] Django doesn't support that. > > + > > + def get_absolute_url(self): > > + return reverse('series', kwargs={ 'series': self.pk }) > > + > > + def dump(self): > > + print('') > > + print('===') > > + print('Series: %s' % self) > > + print(' version %d' % self.version) > > + for rev in self.revisions(): > > + print(' rev %d:' % rev.version) > > + i = 1 > > + for patch in rev.ordered_patches(): > > + print(' patch %d:' % i) > > + print(' subject: %s' % patch.name) > > + print(' msgid : %s' % patch.msgid) > > + i += 1 > > > No need reinventing the wheel: override the '__str__' (not the '__repr__') function instead This is for debugging only and contains too much details to be part of __str__.
On Mon, Oct 19, 2015 at 12:18:58PM +0100, Damien Lespiau wrote: > On Sat, Oct 10, 2015 at 12:21:15AM +0100, Finucane, Stephen wrote: > > > +class Series(models.Model): > > > + project = models.ForeignKey(Project) > > > + name = models.CharField(max_length=200, null=True, blank=False) > > > + submitter = models.ForeignKey(Person, related_name='submitters') > > > + reviewer = models.ForeignKey(User, related_name='reviewers', > > > null=True, > > > + blank=True) > > > + submitted = models.DateTimeField(default=datetime.datetime.now) > > > > Potential edge case: what happens if a series doesn't have a cover > > letter (and therefore no email to get the "submitted" time from)? > > submitted is the timestamp of the row creation, disregarding if the > series has a cover letter or not. No email is getting parsed to set that > field. Actually this is not true. I forgot I changed that behaviour :/ So submitted is taken from the mail headers, each email of the series being inspected and the earliest timestamp taken.
> On Sat, Oct 10, 2015 at 12:21:15AM +0100, Finucane, Stephen wrote: > > > +class Series(models.Model): > > > + project = models.ForeignKey(Project) > > > + name = models.CharField(max_length=200, null=True, blank=False) > > > + submitter = models.ForeignKey(Person, related_name='submitters') > > > + reviewer = models.ForeignKey(User, related_name='reviewers', > > > null=True, > > > + blank=True) > > > + submitted = models.DateTimeField(default=datetime.datetime.now) > > > > Potential edge case: what happens if a series doesn't have a cover > > letter (and therefore no email to get the "submitted" time from)? > > submitted is the timestamp of the row creation, disregarding if the > series has a cover letter or not. No email is getting parsed to set that > field. > > > > + last_updated = models.DateTimeField(auto_now=True) > > > + # Caches the latest version so we can display it without looking > at > > > the max > > > + # of all SeriesRevision.version > > > + version = models.IntegerField(default=1) > > > + # This is the number of patches of the latest version. > > > + n_patches = models.IntegerField(default=0) > > > + > > > + def __unicode__(self): > > > + return self.name > > > + > > > + def revisions(self): > > > + return SeriesRevision.objects.filter(series=self) > > > + > > > + def latest_revision(self): > > > + return self.revisions().reverse()[0] > > > > return self.revisions[-1] > > Django doesn't support that. Right you are: my mistake. > > > + > > > + def get_absolute_url(self): > > > + return reverse('series', kwargs={ 'series': self.pk }) > > > + > > > + def dump(self): > > > + print('') > > > + print('===') > > > + print('Series: %s' % self) > > > + print(' version %d' % self.version) > > > + for rev in self.revisions(): > > > + print(' rev %d:' % rev.version) > > > + i = 1 > > > + for patch in rev.ordered_patches(): > > > + print(' patch %d:' % i) > > > + print(' subject: %s' % patch.name) > > > + print(' msgid : %s' % patch.msgid) > > > + i += 1 > > > > > > No need reinventing the wheel: override the '__str__' (not the > '__repr__') function instead > > This is for debugging only and contains too much details to be part of > __str__. Ehh, we could get away with it would be inconsistent with the rest of the '__str__' functions in that file. Given this (and other replies): Acked-by: Stephen Finucane <stephen.finucane@intel.com.
diff --git a/patchwork/models.py b/patchwork/models.py index a1c2974..68673bf 100644 --- a/patchwork/models.py +++ b/patchwork/models.py @@ -410,6 +410,89 @@ class BundlePatch(models.Model): unique_together = [('bundle', 'patch')] ordering = ['order'] +# This Model represents the "top level" Series, an object that doesn't change +# with the various versions of patches sent to the mailing list. +class Series(models.Model): + project = models.ForeignKey(Project) + name = models.CharField(max_length=200, null=True, blank=False) + submitter = models.ForeignKey(Person, related_name='submitters') + reviewer = models.ForeignKey(User, related_name='reviewers', null=True, + blank=True) + submitted = models.DateTimeField(default=datetime.datetime.now) + last_updated = models.DateTimeField(auto_now=True) + # Caches the latest version so we can display it without looking at the max + # of all SeriesRevision.version + version = models.IntegerField(default=1) + # This is the number of patches of the latest version. + n_patches = models.IntegerField(default=0) + + def __unicode__(self): + return self.name + + def revisions(self): + return SeriesRevision.objects.filter(series=self) + + def latest_revision(self): + return self.revisions().reverse()[0] + + def get_absolute_url(self): + return reverse('series', kwargs={ 'series': self.pk }) + + def dump(self): + print('') + print('===') + print('Series: %s' % self) + print(' version %d' % self.version) + for rev in self.revisions(): + print(' rev %d:' % rev.version) + i = 1 + for patch in rev.ordered_patches(): + print(' patch %d:' % i) + print(' subject: %s' % patch.name) + print(' msgid : %s' % patch.msgid) + i += 1 + +# A 'revision' of a series. Resending a new version of a patch or a full new +# iteration of a series will create a new revision. +class SeriesRevision(models.Model): + series = models.ForeignKey(Series) + version = models.IntegerField(default=1) + root_msgid = models.CharField(max_length=255) + cover_letter = models.TextField(null = True, blank = True) + patches = models.ManyToManyField(Patch, through = 'SeriesRevisionPatch') + + class Meta: + unique_together = [('series', 'version')] + ordering = ['version'] + + def ordered_patches(self): + return self.patches.order_by('seriesrevisionpatch__order') + + def add_patch(self, patch, order): + # see if the patch is already in this revision + if SeriesRevisionPatch.objects.filter(revision=self, + patch=patch).count(): + raise Exception("patch is already in revision") + + sp = SeriesRevisionPatch.objects.create(revision=self, patch=patch, + order=order) + sp.save() + + def __unicode__(self): + if hasattr(self, 'series'): + return self.series.name + " (rev " + str(self.version) + ")" + else: + return "New revision" + " (rev " + str(self.version) + ")" + +class SeriesRevisionPatch(models.Model): + patch = models.ForeignKey(Patch) + revision = models.ForeignKey(SeriesRevision) + order = models.IntegerField() + + class Meta: + unique_together = [('revision', 'patch'), ('revision', 'order')] + ordering = ['order'] + class EmailConfirmation(models.Model): validity = datetime.timedelta(days = settings.CONFIRMATION_VALIDITY_DAYS) type = models.CharField(max_length = 20, choices = [
v2: Add 'order' metadata to revisions as they do have a natural ordering. v3: Add a couple of utility functions to Series and SeriesRevision v4: Provide a get_absolute_url() method on Series v5: Add a dump() method to series, handy for debugging Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> --- patchwork/models.py | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+)