2010-02-25 20:00:03 +03:00
|
|
|
# -*- coding: utf-8 -*-
|
2010-04-14 02:00:03 +04:00
|
|
|
import itertools
|
|
|
|
|
2009-10-23 02:38:11 +04:00
|
|
|
from django.db import models
|
|
|
|
|
2010-02-04 08:13:44 +03:00
|
|
|
import caching.base
|
|
|
|
|
2010-01-29 04:59:26 +03:00
|
|
|
import amo.models
|
2010-01-23 03:52:41 +03:00
|
|
|
from applications.models import Application, AppVersion
|
2010-04-14 02:00:03 +04:00
|
|
|
from files.models import File
|
2010-02-23 22:47:16 +03:00
|
|
|
from translations.fields import TranslatedField, PurifiedField
|
2010-02-04 08:13:44 +03:00
|
|
|
from users.models import UserProfile
|
2009-10-23 02:38:11 +04:00
|
|
|
|
2010-02-25 21:46:19 +03:00
|
|
|
from . import compare
|
|
|
|
|
2009-10-23 02:38:11 +04:00
|
|
|
|
2010-01-29 04:59:26 +03:00
|
|
|
class Version(amo.models.ModelBase):
|
2010-04-14 02:00:03 +04:00
|
|
|
addon = models.ForeignKey('addons.Addon', related_name='versions')
|
2010-01-20 20:45:05 +03:00
|
|
|
license = models.ForeignKey('License', null=True)
|
2010-02-23 22:47:16 +03:00
|
|
|
releasenotes = PurifiedField()
|
2010-03-06 04:37:13 +03:00
|
|
|
approvalnotes = models.TextField(default='', null=True)
|
2009-12-31 03:57:36 +03:00
|
|
|
version = models.CharField(max_length=255, default=0)
|
2009-10-23 02:38:11 +04:00
|
|
|
|
2010-01-29 04:59:26 +03:00
|
|
|
class Meta(amo.models.ModelBase.Meta):
|
2009-10-23 02:38:11 +04:00
|
|
|
db_table = 'versions'
|
2010-03-04 00:30:00 +03:00
|
|
|
ordering = ['-created', '-modified']
|
2010-02-02 23:22:24 +03:00
|
|
|
|
2010-02-25 21:46:19 +03:00
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
super(Version, self).__init__(*args, **kwargs)
|
|
|
|
self.__dict__.update(compare.version_dict(self.version or ''))
|
|
|
|
|
2010-02-18 02:56:17 +03:00
|
|
|
def __unicode__(self):
|
|
|
|
return self.version
|
|
|
|
|
2010-04-14 02:00:03 +04:00
|
|
|
@amo.cached_property(writable=True)
|
2010-02-04 09:15:02 +03:00
|
|
|
def compatible_apps(self):
|
|
|
|
"""Get a mapping of {APP: ApplicationVersion}."""
|
2010-04-17 03:19:49 +04:00
|
|
|
avs = self.apps.select_related(depth=1)
|
2010-04-14 02:00:03 +04:00
|
|
|
return self._compat_map(avs)
|
|
|
|
|
|
|
|
@amo.cached_property(writable=True)
|
|
|
|
def all_files(self):
|
|
|
|
"""Shortcut for list(self.files.all()). Heavily cached."""
|
|
|
|
return list(self.files.all())
|
2010-02-04 09:15:02 +03:00
|
|
|
|
|
|
|
# TODO(jbalogh): Do we want names or Platforms?
|
2010-02-06 01:45:23 +03:00
|
|
|
@amo.cached_property
|
2010-02-04 09:15:02 +03:00
|
|
|
def supported_platforms(self):
|
|
|
|
"""Get a list of supported platform names."""
|
2010-03-04 00:30:00 +03:00
|
|
|
return list(set(amo.PLATFORMS[f.platform_id]
|
2010-04-14 02:00:03 +04:00
|
|
|
for f in self.all_files))
|
2009-12-31 03:57:36 +03:00
|
|
|
|
2010-03-02 16:34:07 +03:00
|
|
|
@amo.cached_property
|
|
|
|
def has_files(self):
|
2010-04-14 02:00:03 +04:00
|
|
|
return bool(self.all_files)
|
2010-03-02 16:34:07 +03:00
|
|
|
|
2010-03-09 22:50:56 +03:00
|
|
|
@amo.cached_property
|
|
|
|
def is_unreviewed(self):
|
2010-04-14 02:00:03 +04:00
|
|
|
return filter(lambda f: f.status == amo.STATUS_UNREVIEWED,
|
|
|
|
self.all_files)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def _compat_map(cls, avs):
|
|
|
|
apps = {}
|
|
|
|
for av in avs:
|
|
|
|
app_id = av.application_id
|
|
|
|
if app_id in amo.APP_IDS:
|
|
|
|
apps[amo.APP_IDS[app_id]] = av
|
|
|
|
return apps
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def transformer(cls, versions):
|
|
|
|
"""Attach all the compatible apps and files to the versions."""
|
|
|
|
if not versions:
|
|
|
|
return
|
|
|
|
|
|
|
|
avs = (ApplicationsVersions.objects.filter(version__in=versions)
|
|
|
|
.select_related(depth=1).order_by('version').no_cache())
|
|
|
|
files = (File.objects.filter(version__in=versions).order_by('version')
|
|
|
|
.select_related('version').no_cache())
|
|
|
|
|
|
|
|
def rollup(xs):
|
|
|
|
groups = itertools.groupby(xs, key=lambda x: x.version_id)
|
|
|
|
return dict((k, list(vs)) for k, vs in groups)
|
|
|
|
|
|
|
|
av_dict, file_dict = rollup(avs), rollup(files)
|
|
|
|
|
|
|
|
for version in versions:
|
|
|
|
v_id = version.id
|
|
|
|
version.compatible_apps = cls._compat_map(av_dict.get(v_id, []))
|
|
|
|
version.all_files = file_dict.get(v_id, [])
|
2010-03-09 22:50:56 +03:00
|
|
|
|
2009-12-31 03:57:36 +03:00
|
|
|
|
2010-01-29 04:59:26 +03:00
|
|
|
class License(amo.models.ModelBase):
|
2010-03-01 22:21:09 +03:00
|
|
|
"""
|
|
|
|
Custom as well as built-in licenses.
|
|
|
|
A name of -1 indicates a custom license, all names >= 0 are built-in.
|
|
|
|
Built-in licenses are defined in amo.__init__
|
|
|
|
"""
|
|
|
|
|
|
|
|
_name_field = models.IntegerField(null=False,
|
|
|
|
default=amo.LICENSE_CUSTOM.id,
|
|
|
|
db_column='name')
|
|
|
|
_custom_text = TranslatedField(db_column='text')
|
2009-12-31 03:57:36 +03:00
|
|
|
|
2010-01-29 04:59:26 +03:00
|
|
|
class Meta(amo.models.ModelBase.Meta):
|
2009-12-31 03:57:36 +03:00
|
|
|
db_table = 'licenses'
|
2010-01-14 03:01:23 +03:00
|
|
|
|
2010-03-01 22:21:09 +03:00
|
|
|
def __unicode__(self):
|
|
|
|
return self.name
|
|
|
|
|
|
|
|
@property
|
2010-03-02 13:07:27 +03:00
|
|
|
def license_type(self):
|
2010-03-01 22:21:09 +03:00
|
|
|
return amo.LICENSE_IDS.get(self._name_field, amo.LICENSE_CUSTOM)
|
|
|
|
|
2010-03-02 13:07:27 +03:00
|
|
|
@license_type.setter
|
|
|
|
def license_type(self, license):
|
2010-03-01 22:21:09 +03:00
|
|
|
assert license in amo.LICENSES
|
|
|
|
self._name_field = license.id
|
|
|
|
|
|
|
|
@property
|
|
|
|
def is_custom(self):
|
|
|
|
"""is this a custom, not built-in, license?"""
|
2010-03-02 13:07:27 +03:00
|
|
|
return self.license_type.id == amo.LICENSE_CUSTOM.id
|
2010-03-01 22:21:09 +03:00
|
|
|
|
|
|
|
@property
|
|
|
|
def name(self):
|
2010-03-02 13:07:27 +03:00
|
|
|
return self.license_type.name
|
2010-03-01 22:21:09 +03:00
|
|
|
|
|
|
|
@property
|
|
|
|
def text(self):
|
|
|
|
if self.is_custom:
|
|
|
|
return self._custom_text
|
|
|
|
else:
|
2010-03-02 13:07:27 +03:00
|
|
|
return self.license_type.text()
|
2010-03-01 22:21:09 +03:00
|
|
|
|
|
|
|
@text.setter
|
|
|
|
def text(self, value):
|
|
|
|
if value:
|
2010-03-02 13:07:27 +03:00
|
|
|
self.license_type = amo.LICENSE_CUSTOM
|
2010-03-01 22:21:09 +03:00
|
|
|
self._custom_text = value
|
|
|
|
|
|
|
|
@property
|
|
|
|
def url(self):
|
2010-03-02 13:07:27 +03:00
|
|
|
return self.license_type.url
|
2010-03-01 22:21:09 +03:00
|
|
|
|
2010-01-14 03:01:23 +03:00
|
|
|
|
2010-01-29 04:59:26 +03:00
|
|
|
class VersionComment(amo.models.ModelBase):
|
2010-01-14 03:01:23 +03:00
|
|
|
"""Editor comments for version discussion threads."""
|
|
|
|
version = models.ForeignKey(Version)
|
2010-01-18 13:51:34 +03:00
|
|
|
user = models.ForeignKey(UserProfile)
|
2010-01-14 03:01:23 +03:00
|
|
|
reply_to = models.ForeignKey(Version, related_name="reply_to", null=True)
|
|
|
|
subject = models.CharField(max_length=1000)
|
|
|
|
comment = models.TextField()
|
|
|
|
|
2010-01-29 04:59:26 +03:00
|
|
|
class Meta(amo.models.ModelBase.Meta):
|
2010-01-14 03:01:23 +03:00
|
|
|
db_table = 'versioncomments'
|
|
|
|
|
|
|
|
|
2010-01-29 04:59:26 +03:00
|
|
|
class VersionSummary(amo.models.ModelBase):
|
2010-04-14 02:00:03 +04:00
|
|
|
addon = models.ForeignKey('addons.Addon')
|
2010-01-14 03:01:23 +03:00
|
|
|
version = models.ForeignKey(Version)
|
|
|
|
application = models.ForeignKey(Application)
|
|
|
|
min = models.IntegerField(null=True)
|
|
|
|
max = models.IntegerField(null=True)
|
|
|
|
|
2010-01-29 04:59:26 +03:00
|
|
|
class Meta(amo.models.ModelBase.Meta):
|
2010-01-14 03:01:23 +03:00
|
|
|
db_table = 'versions_summary'
|
2010-01-23 03:52:41 +03:00
|
|
|
|
|
|
|
|
2010-02-04 08:13:44 +03:00
|
|
|
class ApplicationsVersions(caching.base.CachingMixin, models.Model):
|
2010-01-23 03:52:41 +03:00
|
|
|
|
|
|
|
application = models.ForeignKey(Application)
|
2010-04-17 03:19:49 +04:00
|
|
|
version = models.ForeignKey(Version, related_name='apps')
|
2010-01-27 01:44:12 +03:00
|
|
|
min = models.ForeignKey(AppVersion, db_column='min',
|
|
|
|
related_name='min_set')
|
|
|
|
max = models.ForeignKey(AppVersion, db_column='max',
|
|
|
|
related_name='max_set')
|
2010-01-23 03:52:41 +03:00
|
|
|
|
2010-02-04 08:13:44 +03:00
|
|
|
objects = caching.base.CachingManager()
|
|
|
|
|
2010-01-23 03:52:41 +03:00
|
|
|
class Meta:
|
|
|
|
db_table = u'applications_versions'
|
2010-02-02 23:22:24 +03:00
|
|
|
unique_together = (("application", "version"),)
|
2010-02-25 20:00:03 +03:00
|
|
|
|
|
|
|
def __unicode__(self):
|
2010-03-11 00:14:12 +03:00
|
|
|
return u'%s: %s - %s' % (self.application, self.min, self.max)
|