addons-server/apps/versions/models.py

217 строки
6.9 KiB
Python
Исходник Обычный вид История

# -*- coding: utf-8 -*-
import itertools
import os
from django.conf import settings
2009-10-23 02:38:11 +04:00
from django.db import models
import commonware.log
2010-02-04 08:13:44 +03:00
import caching.base
import amo
import amo.models
from amo.urlresolvers import reverse
from applications.models import Application, AppVersion
from files.models import File, Platform
from translations.fields import (TranslatedField, PurifiedField,
LinkifiedField)
2010-02-04 08:13:44 +03:00
from users.models import UserProfile
2009-10-23 02:38:11 +04:00
from . import compare
log = commonware.log.getLogger('z.versions')
2009-10-23 02:38:11 +04:00
class Version(amo.models.ModelBase):
addon = models.ForeignKey('addons.Addon', related_name='versions')
2010-01-20 20:45:05 +03:00
license = models.ForeignKey('License', null=True)
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
class Meta(amo.models.ModelBase.Meta):
2009-10-23 02:38:11 +04:00
db_table = 'versions'
ordering = ['-created', '-modified']
def __init__(self, *args, **kwargs):
super(Version, self).__init__(*args, **kwargs)
self.__dict__.update(compare.version_dict(self.version or ''))
def __unicode__(self):
return self.version
@classmethod
def from_upload(cls, upload, addon):
2010-11-16 03:58:42 +03:00
from . import utils
# TODO: license, relnotes
2010-11-16 03:58:42 +03:00
data = utils.parse_xpi(upload.path, addon)
try:
license = addon.versions.latest().license_id
except Version.DoesNotExist:
license = None
v = cls.objects.create(addon=addon, version=data['version'],
license_id=license)
log.debug('New version: %r (%s) from %r' % (v, v.id, upload))
# TODO: platforms?
File.from_upload(upload, v,
Platform.objects.get(id=amo.PLATFORM_ALL.id))
# appversions
AV = ApplicationsVersions
for app in data['apps']:
AV(version=v, min=app.min, max=app.max,
application_id=app.id).save()
# TODO: share more with XPIForm
return v
@property
def path_prefix(self):
return os.path.join(settings.ADDONS_PATH, str(self.addon_id))
2010-10-23 04:30:58 +04:00
def license_url(self):
return reverse('addons.license', args=[self.addon_id, self.version])
2010-08-13 20:24:36 +04:00
def flush_urls(self):
return self.addon.flush_urls()
2010-11-06 00:48:05 +03:00
def get_url_path(self):
return reverse('addons.versions', args=(self.addon.id, self.version,))
def delete(self):
2010-11-20 00:51:36 +03:00
amo.log(amo.LOG.DELETE_VERSION, self.addon, str(self.version))
super(Version, self).delete()
@amo.cached_property(writable=True)
def compatible_apps(self):
"""Get a mapping of {APP: ApplicationVersion}."""
avs = self.apps.select_related(depth=1)
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())
# TODO(jbalogh): Do we want names or Platforms?
2010-02-06 01:45:23 +03:00
@amo.cached_property
def supported_platforms(self):
"""Get a list of supported platform names."""
return list(set(amo.PLATFORMS[f.platform_id]
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):
return bool(self.all_files)
2010-03-02 16:34:07 +03:00
@amo.cached_property
def is_unreviewed(self):
return filter(lambda f: f.status in amo.UNREVIEWED_STATUSES,
self.all_files)
@amo.cached_property
def is_beta(self):
return filter(lambda f: f.status == amo.STATUS_BETA,
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__id').no_cache())
files = (File.objects.filter(version__in=versions)
.order_by('version__id').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, [])
2009-12-31 03:57:36 +03:00
class LicenseManager(amo.models.ManagerBase):
def builtins(self):
return self.filter(builtin__gt=0).order_by('builtin')
2009-12-31 03:57:36 +03:00
class License(amo.models.ModelBase):
OTHER = 0
name = TranslatedField(db_column='name')
url = models.URLField(null=True)
builtin = models.PositiveIntegerField(default=OTHER)
text = LinkifiedField()
on_form = models.BooleanField(default=False,
help_text='Is this a license choice in the devhub?')
some_rights = models.BooleanField(default=False,
help_text='Show "Some Rights Reserved" instead of the license name?')
icons = models.CharField(max_length=255, null=True,
help_text='Space-separated list of icon identifiers.')
objects = LicenseManager()
class Meta:
2009-12-31 03:57:36 +03:00
db_table = 'licenses'
2010-01-14 03:01:23 +03:00
def __unicode__(self):
return '%s %s' % (self.id, self.name)
2010-01-14 03:01:23 +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)
user = models.ForeignKey(UserProfile)
2010-08-05 00:25:09 +04:00
reply_to = models.ForeignKey(Version, related_name="reply_to",
db_column='reply_to', null=True)
2010-01-14 03:01:23 +03:00
subject = models.CharField(max_length=1000)
comment = models.TextField()
class Meta(amo.models.ModelBase.Meta):
2010-01-14 03:01:23 +03:00
db_table = 'versioncomments'
class VersionSummary(amo.models.ModelBase):
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)
class Meta(amo.models.ModelBase.Meta):
2010-01-14 03:01:23 +03:00
db_table = 'versions_summary'
2010-02-04 08:13:44 +03:00
class ApplicationsVersions(caching.base.CachingMixin, models.Model):
application = models.ForeignKey(Application)
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-02-04 08:13:44 +03:00
objects = caching.base.CachingManager()
class Meta:
db_table = u'applications_versions'
unique_together = (("application", "version"),)
def __unicode__(self):
return u'%s %s - %s' % (self.application, self.min, self.max)