Guest User

Untitled

a guest
Jul 20th, 2018
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.76 KB | None | 0 0
  1. cat aur/models.py
  2. from django.db import models
  3. from django.db import transaction
  4. from django.db import IntegrityError
  5. from django.contrib.auth.models import User
  6. from django.core.mail import send_mass_mail
  7. from django.db.models import signals, permalink
  8. from django.dispatch import dispatcher
  9. from django.template.loader import render_to_string
  10. from django.utils.encoding import smart_unicode
  11.  
  12. from tagging.fields import TagField
  13.  
  14. from datetime import datetime
  15. import os
  16.  
  17. def _get_package_upload_to(instance, filename):
  18. """Returns a string, replacing the name placeholder with a packages name
  19.  
  20. *instance* should be a :class:`PackageFile` or :class:`Package` instance.
  21.  
  22. *filename* should be a a string with a named placeholder where the name
  23. should be inserted, e.g. ``'%(name)s/sources/PKGBUILD'``.
  24.  
  25. .. note::
  26.  
  27. This is meant for use by :class:`PackageFile` and :class:`Package` as
  28. the *upload_to* callable
  29. """
  30. if hasattr(instance, 'package'):
  31. package = instance.package
  32. else:
  33. package = instance
  34. return os.path.join('packages', filename % {'name': package.name})
  35.  
  36.  
  37. class Architecture(models.Model):
  38. name = models.CharField(max_length=10)
  39.  
  40. def __unicode__(self):
  41. return self.name
  42.  
  43.  
  44. class Repository(models.Model):
  45. name = models.CharField(max_length=20)
  46.  
  47. def __unicode__(self):
  48. return self.name
  49.  
  50. class Meta:
  51. verbose_name_plural = 'repositories'
  52.  
  53.  
  54. class License(models.Model):
  55. name = models.CharField(max_length=24)
  56.  
  57. def __unicode__(self):
  58. return self.name
  59.  
  60.  
  61. class Group(models.Model):
  62. name = models.CharField(max_length=10)
  63.  
  64. def __unicode__(self):
  65. return self.name
  66.  
  67.  
  68. class Provision(models.Model):
  69. name = models.CharField(max_length=30)
  70.  
  71. def __unicode__(self):
  72. return self.name
  73.  
  74.  
  75. class Package(models.Model):
  76. name = models.CharField(unique=True, max_length=30, editable=False)
  77. version = models.CharField(max_length=20)
  78. release = models.SmallIntegerField()
  79. description = models.CharField(max_length=180)
  80. url = models.CharField(max_length=200, null=True, blank=True)
  81. maintainers = models.ManyToManyField(User)
  82. repository = models.ForeignKey(Repository)
  83. tags = TagField()
  84. slug = models.SlugField(editable=False)
  85. tarball = models.FileField(upload_to=_get_package_upload_to)
  86. licenses = models.ManyToManyField(License, null=True, blank=True)
  87. architectures = models.ManyToManyField(Architecture)
  88. depends = models.ManyToManyField('self', null=True, blank=True,
  89. related_name="reverse_depends", symmetrical=False)
  90. make_depends = models.ManyToManyField('self', null=True, blank=True,
  91. related_name="reverse_make_depends", symmetrical=False)
  92. replaces = models.ManyToManyField('self', null=True, blank=True,
  93. related_name='reverse_replaces', symmetrical=False)
  94. conflicts = models.ManyToManyField('self', null=True, blank=True,
  95. related_name="reverse_conflicts", symmetrical=False)
  96. provides = models.ManyToManyField(Provision, null=True, blank=True)
  97. deleted = models.BooleanField(default=False)
  98. outdated = models.BooleanField(default=False)
  99. added = models.DateTimeField(auto_now_add=True)
  100. updated = models.DateTimeField(auto_now=True)
  101. groups = models.ManyToManyField(Group, null=True, blank=True)
  102.  
  103. def __unicode__(self):
  104. return u'%s %s' % (self.name, self.version)
  105.  
  106. def get_arch(self):
  107. return ', '.join(map(smart_unicode, self.architectures.all()))
  108. get_arch.short_description = 'architectures'
  109.  
  110. def get_tarball_basename(self):
  111. """Return the basename of the absolute path to the tarball"""
  112. return os.path.basename(self.tarball.path)
  113.  
  114. def get_absolute_url(self):
  115. return ('aur-package_detail', [self.slug,])
  116. get_absolute_url = permalink(get_absolute_url)
  117.  
  118. def save(self):
  119. if not self.slug:
  120. import re
  121. slug = re.sub('[^\w\s-]', '', self.name).strip().lower()
  122. slug = re.sub('[-\s]+', '-', slug)
  123. self.slug = slug
  124. super(Package, self).save()
  125.  
  126. class Meta:
  127. ordering = ('-updated',)
  128. get_latest_by = 'updated'
  129.  
  130.  
  131. class PackageFile(models.Model):
  132. package = models.ForeignKey(Package)
  133. # filename for local sources and url for external
  134. filename = models.FileField(upload_to=_get_package_upload_to, null=True, blank=True)
  135. url = models.URLField(null=True, blank=True)
  136.  
  137. def get_absolute_url(self):
  138. if self.filename:
  139. return self.filename.url
  140. else:
  141. return self.url
  142.  
  143. def get_filename(self):
  144. if self.filename:
  145. return os.path.basename(self.filename.path)
  146. else:
  147. return self.url
  148.  
  149. def __unicode__(self):
  150. return self.filename
  151.  
  152. class PackageHash(models.Model):
  153. # sha512 hashes are 128 characters
  154. hash = models.CharField(max_length=128, primary_key=True)
  155. type = models.CharField(max_length=12)
  156. file = models.ForeignKey(PackageFile)
  157.  
  158. def __unicode__(self):
  159. return self.hash
  160.  
  161. class Meta:
  162. verbose_name_plural = 'package hashes'
  163.  
  164.  
  165. class Comment(models.Model):
  166. package = models.ForeignKey(Package)
  167. parent = models.ForeignKey('self', null=True, blank=True)
  168. user = models.ForeignKey(User)
  169. message = models.TextField()
  170. added = models.DateTimeField(auto_now_add=True)
  171. ip = models.IPAddressField()
  172. hidden = models.BooleanField(default=False)
  173.  
  174. def __unicode__(self):
  175. return self.message
  176.  
  177.  
  178. class PackageNotification(models.Model):
  179. user = models.ForeignKey(User)
  180. package = models.ForeignKey(Package)
  181.  
  182. def __unicode__(self):
  183. return u"%s's subscription to %s updates" % (self.user.username,
  184. self.package.name)
  185.  
  186.  
  187. class Vote(models.Model):
  188. user = models.ForeignKey(User)
  189. package = models.ForeignKey(Package)
  190. added = models.DateTimeField(auto_now_add=True)
  191.  
  192. def __unicode__(self):
  193. return u"%s's vote for %s" % (self.user.username,
  194. self.package.name)
  195.  
  196. class Meta:
  197. unique_together = (("user", "package"),)
  198.  
  199. # Should this be here?
  200. def email_package_updates(sender, instance, signal, *args, **kwargs):
  201. from django.conf import settings
  202. """Send notification to users of modification to a Package"""
  203. subject = "Archlinux AUR: %s updated" % instance.name
  204. mail_list = []
  205. notifications = PackageNotification.objects.filter(package=instance)
  206. for notification in notifications:
  207. if not notification.user.email:
  208. continue
  209. message = render_to_string('aur/email_notification.txt', {
  210. 'package': instance,
  211. 'user': notification.user,
  212. })
  213. mail_list.append((subject, message, settings.DEFAULT_FROM_EMAIL,
  214. (notification.user.email,)))
  215. return send_mass_mail(mail_list)
  216.  
  217.  
  218. def remove_packagefile_filename(sender, instance, signal, *args, **kwargs):
  219. """Remove PackageFile's file"""
  220. if instance.filename:
  221. instance.filename.delete()
  222.  
  223. def remove_package_tarball(sender, instance, signal, *args, **kwargs):
  224. """Remove Package's tarball"""
  225. instance.tarball.delete()
  226.  
  227. # Send notifications of updates to users on saves and deltion of packages
  228. signals.post_save.connect(email_package_updates, sender=Package)
  229. signals.post_delete.connect(email_package_updates, sender=Package)
  230. # Remove files when packages get deleted
  231. # Django doesn't call each instance's delete() on cascade, but it does send
  232. # pre_delete signals
  233. signals.pre_delete.connect(remove_packagefile_filename, sender=PackageFile)
  234. signals.pre_delete.connect(remove_package_tarball, sender=Package)
Add Comment
Please, Sign In to add comment