public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
From: "Slava Bacherikov" <slava@bacherikov.org.ua>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/gentoo-packages:master commit in: gpackages/apps/packages/, gpackages/libs/package_info/package_backends/
Date: Thu,  5 Jul 2012 23:27:09 +0000 (UTC)	[thread overview]
Message-ID: <1341510228.e6a1805fa32a963d1728c1e95797a13874662200.bacher09@gentoo> (raw)

commit:     e6a1805fa32a963d1728c1e95797a13874662200
Author:     Slava Bacherikov <slava <AT> bacher09 <DOT> org>
AuthorDate: Thu Jul  5 17:43:48 2012 +0000
Commit:     Slava Bacherikov <slava <AT> bacherikov <DOT> org <DOT> ua>
CommitDate: Thu Jul  5 17:43:48 2012 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/gentoo-packages.git;a=commit;h=e6a1805f

Add stats calculating

---
 gpackages/apps/packages/models.py                  |   92 ++++++++++++++++++--
 gpackages/apps/packages/stats.py                   |   31 +++++++
 .../libs/package_info/package_backends/pkgcore.py  |    6 ++
 .../libs/package_info/package_backends/portage.py  |    6 ++
 4 files changed, 127 insertions(+), 8 deletions(-)

diff --git a/gpackages/apps/packages/models.py b/gpackages/apps/packages/models.py
index 51b839e..efb4638 100644
--- a/gpackages/apps/packages/models.py
+++ b/gpackages/apps/packages/models.py
@@ -6,6 +6,7 @@ from package_info.generic import get_from_kwargs_and_del
 from package_info.repo_info import REPOS_TYPE
 # relative
 from .keywords import KeywordRepr
+from .stats import StatsMixin
 #from utils import get_link
 from package_info.validators import validate_url, validate_email, \
                                     validate_name
@@ -90,12 +91,17 @@ class ArchesModel(models.Model):
     def __unicode__(self):
         return self.name
 
-class RepositoryModel(AbstractDateTimeModel):
+class RepositoryModel(StatsMixin, AbstractDateTimeModel):
     QUALITY_CHOICES = ( (0, 'stable'),
                         (1, 'testing'),
                         (2, 'experimental'),
                       )
 
+    stats_params = (
+        ('packages_count', 'packagemodel'),
+        ('ebuilds_count', 'packagemodel__ebuildmodel'),
+    )
+
     def __init__(self, *args, **kwargs):
         repo = get_from_kwargs_and_del('repo', kwargs)
         super(RepositoryModel, self).__init__(*args, **kwargs)
@@ -113,6 +119,12 @@ class RepositoryModel(AbstractDateTimeModel):
     official = models.BooleanField(default = False)
     quality = models.PositiveSmallIntegerField(choices = QUALITY_CHOICES)
 
+    # Maybe in future auto generate this field by metaclass ?
+    # For fast stats
+    packages_count = models.PositiveIntegerField(default = 0)
+    ebuilds_count = models.PositiveIntegerField(default = 0)
+
+
     objects = managers.RepositoryManager()
 
     def init_by_repo(self, repo):
@@ -194,7 +206,7 @@ class RepositorySourceModel(models.Model):
     def __unicode__(self):
         return self.url
 
-class CategoryModel(models.Model):
+class CategoryModel(StatsMixin, models.Model):
     def __init__(self, *args, **kwargs):
         super(CategoryModel, self).__init__(*args, **kwargs)
 
@@ -202,6 +214,13 @@ class CategoryModel(models.Model):
         if isinstance(category, AbstractCategory):  
             self.update_by_category(category)
 
+    stats_params = (
+        ('virtual_packages_count', 'virtualpackagemodel'),
+        ('packages_count', 'virtualpackagemodel__packagemodel'),
+        ('repositories_count', 'virtualpackagemodel__packagemodel__repository'),
+        ('ebuilds_count', 'virtualpackagemodel__packagemodel__ebuildmodel'),
+    )
+
     def update_by_category(self, category):
         self.description = category.metadata.default_descr
         self.metadata_hash = category.metadata_sha1
@@ -212,21 +231,47 @@ class CategoryModel(models.Model):
     category = models.CharField(unique = True, max_length = 70, db_index = True)
     description = models.TextField(blank = True, null = True)
     metadata_hash = models.CharField(max_length = 128, null = True)
+
+    # Maybe in future auto generate this field by metaclass ?
+    # For fast stats
+    virtual_packages_count = models.PositiveIntegerField(default = 0)
+    packages_count = models.PositiveIntegerField(default = 0)
+    repositories_count = models.PositiveIntegerField(default = 0)
+    ebuilds_count =  models.PositiveIntegerField(default = 0)
     
     def __unicode__(self):
         return unicode(self.category)
 
-class MaintainerModel(AbstractDateTimeModel):
+class MaintainerModel(StatsMixin, AbstractDateTimeModel):
 
     def __init__(self, *args, **kwargs):
         maintainer = get_from_kwargs_and_del('maintainer', kwargs)
         super(MaintainerModel, self).__init__(*args, **kwargs)
         if maintainer is not None:
             self.init_by_maintainer(maintainer)
+
+    stats_params = (
+           ('packages_count', 'packagemodel'),
+           ('herds_count', 'herdsmodel'),
+           ('ebuilds_count', 'packagemodel__ebuildmodel'),
+           ('repositories_count', 'packagemodel__ebuildmodel'),
+           ('news_author_count', 'author_news_set'),
+           ('news_translator_count', 'translator_news_set')
+        )
         
     name = models.CharField(max_length = 255, blank = True, null = True)
     email = models.EmailField(unique = True, validators = [validate_email], db_index = True)
 
+    # For fast stats
+    # Maybe use django-composition ?
+    # Maybe in future auto generate this field by metaclass ?
+    herds_count = models.PositiveIntegerField(default = 0)
+    packages_count = models.PositiveIntegerField(default = 0)
+    ebuilds_count =  models.PositiveIntegerField(default = 0)
+    repositories_count =  models.PositiveIntegerField(default = 0)
+    news_author_count = models.PositiveIntegerField(default = 0)
+    news_translator_count = models.PositiveIntegerField(default = 0)
+
     objects = managers.MaintainerManager()
 
     def init_by_maintainer(self, maintainer):
@@ -246,7 +291,7 @@ class MaintainerModel(AbstractDateTimeModel):
     class Meta:
         ordering = ('name',)
 
-class HerdsModel(AbstractDateTimeModel):
+class HerdsModel(StatsMixin, AbstractDateTimeModel):
 
     def __init__(self, *args, **kwargs):
         herd = get_from_kwargs_and_del('herd', kwargs)
@@ -254,11 +299,26 @@ class HerdsModel(AbstractDateTimeModel):
         if herd is not None:
             self.init_by_herd(herd)
 
+    stats_params = (
+           ('packages_count', 'packagemodel'),
+           ('maintainers_count', 'maintainers'),
+           ('ebuilds_count', 'packagemodel__ebuildmodel'),
+           ('repositories_count', 'packagemodel__repository'),
+        )
+
     name = models.CharField(unique = True, max_length = 150, db_index = True)
     email = models.EmailField(validators = [validate_email])
     description = models.TextField(blank = True, null = True)
     maintainers = models.ManyToManyField(MaintainerModel, blank = True)
 
+    # For fast stats
+    # Maybe use django-composition ?
+    # Maybe in future auto generate this field by metaclass ?
+    maintainers_count = models.PositiveIntegerField(default = 0)
+    packages_count = models.PositiveIntegerField(default = 0)
+    ebuilds_count = models.PositiveIntegerField(default = 0)
+    repositories_count = models.PositiveIntegerField(default = 0)
+
     objects = managers.HerdsManager()
 
     def init_by_herd(self, herd):
@@ -304,7 +364,8 @@ class VirtualPackageModel(models.Model):
     class Meta:
         unique_together = ('name', 'category')
 
-class PackageModel(AbstractDateTimeModel):
+class PackageModel(StatsMixin, AbstractDateTimeModel):
+
     def __init__(self, *args, **kwargs):
         package_object, category = \
             get_from_kwargs_and_del(('package','category' ), kwargs)
@@ -313,6 +374,9 @@ class PackageModel(AbstractDateTimeModel):
         if isinstance(package_object, AbstarctPackage):
             self.init_by_package(package_object, category = category)
             
+    stats_params = (
+           ('ebuilds_count', 'ebuildmodel'),
+        )
         
     virtual_package = models.ForeignKey(VirtualPackageModel, db_index = True)
     changelog = models.TextField(blank = True, null = True)
@@ -329,6 +393,8 @@ class PackageModel(AbstractDateTimeModel):
     description = models.TextField(blank = True, null = True)
     repository = models.ForeignKey(RepositoryModel, db_index = True)
     # Different versions can have different licenses, or homepages.
+
+    ebuilds_count = models.PositiveIntegerField(default = 0)
     
     objects = managers.PackageManager()
 
@@ -407,10 +473,16 @@ class PackageModel(AbstractDateTimeModel):
         unique_together = ('virtual_package', 'repository')
         ordering = ('-updated_datetime',)
 
-class UseFlagModel(models.Model):
+class UseFlagModel(StatsMixin, models.Model):
+    stats_params = (
+           ('ebuilds_count', 'ebuildmodel'),
+        )
+
     name = models.CharField(unique = True, max_length = 60, db_index = True)
     description = models.TextField(blank = True)
     
+    ebuilds_count = models.PositiveIntegerField(default = 0)
+
     def __unicode__(self):
         return self.name
 
@@ -431,9 +503,14 @@ class UseFlagDescriptionModel(models.Model):
     class Meta:
         unique_together = ('use_flag', 'package')
 
-class LicenseModel(models.Model):
+class LicenseModel(StatsMixin, models.Model):
+    stats_params = (
+           ('ebuilds_count', 'ebuildmodel'),
+        )
+
     name = models.CharField(unique = True, max_length = 60, db_index = True)
     #description = TextField()
+    ebuilds_count = models.PositiveIntegerField(default = 0)
     
     def __unicode__(self):
         return self.name
@@ -648,4 +725,3 @@ class Keyword(models.Model):
     class Meta:
         unique_together = ('ebuild', 'arch')
 
-

diff --git a/gpackages/apps/packages/stats.py b/gpackages/apps/packages/stats.py
new file mode 100644
index 0000000..9bf3efa
--- /dev/null
+++ b/gpackages/apps/packages/stats.py
@@ -0,0 +1,31 @@
+from django.db.models import Count
+from itertools import starmap
+
+gen_prefix = lambda x: x + '_prefix'
+
+def gen_query_dict(params):
+    query_dict = {}
+    for key, value in starmap(lambda x,y: (gen_prefix(x), y), params):
+        query_dict[key] = Count(value, distinct = True)
+
+    return query_dict
+
+def make_query_for_stats(model, params):
+    query_dict = gen_query_dict(params)
+    return model.objects.annotate(**query_dict)
+
+def update_stats(model, params):
+    query = make_query_for_stats(model, params)
+    for obj in query:
+        for key, mykey in starmap(lambda  x,y: (x, gen_prefix(x)), params):
+            setattr(obj, key, getattr(obj, mykey))
+
+        obj.save(force_update = True)
+
+class StatsMixin(object):
+
+    stats_params = ((),)
+
+    @classmethod
+    def calc_stats(cls):
+        update_stats(cls, cls.stats_params)

diff --git a/gpackages/libs/package_info/package_backends/pkgcore.py b/gpackages/libs/package_info/package_backends/pkgcore.py
index 9a17208..2ad6b69 100644
--- a/gpackages/libs/package_info/package_backends/pkgcore.py
+++ b/gpackages/libs/package_info/package_backends/pkgcore.py
@@ -57,6 +57,9 @@ class Portage(PortageMixin):
 
     def __unicode__(self):
         return u'pkgcore'
+
+    def __len__(self):
+        return len(self.repo_list)
         
 class PortTree(PortTreeMixin):
 
@@ -86,6 +89,9 @@ class PortTree(PortTreeMixin):
     def _versions(self):
         return self._repo_obj.versions
 
+    def __len__(self):
+        return len(self.categories)
+
 class Category(CategoryMixin):
     
     __slots__ = ('_repo_obj', 'name')

diff --git a/gpackages/libs/package_info/package_backends/portage.py b/gpackages/libs/package_info/package_backends/portage.py
index 729e6e9..e3707d4 100644
--- a/gpackages/libs/package_info/package_backends/portage.py
+++ b/gpackages/libs/package_info/package_backends/portage.py
@@ -51,6 +51,9 @@ class Portage(PortageMixin):
     def __unicode__(self):
         return u'portage'
 
+    def __len__(self):
+        return len(self.tree_order)
+
 class PortTree(PortTreeMixin):
     "Represent portage tree as object"
 
@@ -72,6 +75,9 @@ class PortTree(PortTreeMixin):
         "Full path to portage tree"
         return self.porttree
 
+    def __len__(self):
+        return len(PORTDB.settings.categories)
+
 class Category(CategoryMixin):
     "Represent category of portage tree as object"
 



             reply	other threads:[~2012-07-05 23:27 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-07-05 23:27 Slava Bacherikov [this message]
  -- strict thread matches above, loose matches on Subject: below --
2012-07-03 21:08 [gentoo-commits] proj/gentoo-packages:master commit in: gpackages/apps/packages/, gpackages/libs/package_info/package_backends/ Slava Bacherikov
2012-07-03 21:08 Slava Bacherikov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1341510228.e6a1805fa32a963d1728c1e95797a13874662200.bacher09@gentoo \
    --to=slava@bacherikov.org.ua \
    --cc=gentoo-commits@lists.gentoo.org \
    --cc=gentoo-dev@lists.gentoo.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox