You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by br...@apache.org on 2013/05/05 05:09:46 UTC

[1/4] git commit: [#6133] avoid div by 0 errors when no data

Updated Branches:
  refs/heads/db/6133 [created] 42eb99325


[#6133] avoid div by 0 errors when no data


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/7c178292
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/7c178292
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/7c178292

Branch: refs/heads/db/6133
Commit: 7c178292697351ff582777c1d76dfc4bf98bd711
Parents: 94cd1ed
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Sat May 4 21:41:45 2013 -0400
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Sat May 4 21:41:45 2013 -0400

----------------------------------------------------------------------
 Allura/allura/model/stats.py |   88 ++++++++++++++++++++-----------------
 1 files changed, 47 insertions(+), 41 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/7c178292/Allura/allura/model/stats.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/stats.py b/Allura/allura/model/stats.py
index 5365503..06ed07d 100644
--- a/Allura/allura/model/stats.py
+++ b/Allura/allura/model/stats.py
@@ -86,7 +86,7 @@ class Stats(MappedClass):
         for val in self['general']:
             if val['category'] is None:
                 for commits in val['commits']:
-                    if commits['language'] is None: 
+                    if commits['language'] is None:
                         if days > 30:
                             return round(float(commits.lines)/days*30, 2)
                         else:
@@ -100,7 +100,7 @@ class Stats(MappedClass):
         for val in self['general']:
             if val['category'] is None:
                 for artifact in val['messages']:
-                    if artifact['messagetype'] is None: 
+                    if artifact['messagetype'] is None:
                         tot = artifact.created+artifact.modified
                         if days > 30:
                             return round(float(tot)/days*30,2)
@@ -153,6 +153,8 @@ class Stats(MappedClass):
     def codeRanking(self):
         res = self.query.find()
         totn = res.count()
+        if totn == 0:
+            return 0
         codcontr = self.getCodeContribution()
         upper = len([x for x in res if x.getCodeContribution() > codcontr])
         return round((totn - upper) * 100.0 / totn, 2)
@@ -160,6 +162,8 @@ class Stats(MappedClass):
     def discussionRanking(self):
         res = self.query.find()
         totn = res.count()
+        if totn == 0:
+            return 0
         disccontr = self.getDiscussionContribution()
         upper=len([x for x in res if x.getDiscussionContribution()>disccontr])
         return round((totn - upper) * 100.0 / totn, 2)
@@ -167,20 +171,22 @@ class Stats(MappedClass):
     def ticketsRanking(self):
         res = self.query.find()
         totn = res.count()
+        if totn == 0:
+            return 0
         ticketscontr = self.getTicketsContribution()
         upper=len([x for x in res if x.getTicketsContribution()>ticketscontr])
         return round((totn - upper) * 100.0 / totn, 2)
 
     def getCommits(self, category = None):
         i = getElementIndex(self.general, category = category)
-        if i is None: 
+        if i is None:
             return dict(number=0, lines=0)
         cat = self.general[i]
         j = getElementIndex(cat.commits, language = None)
         if j is None:
             return dict(number=0, lines=0)
         return dict(
-            number=cat.commits[j]['number'], 
+            number=cat.commits[j]['number'],
             lines=cat.commits[j]['lines'])
 
     def getArtifacts(self, category = None, art_type = None):
@@ -202,10 +208,10 @@ class Stats(MappedClass):
                 revoked=0,
                 averagesolvingtime=None)
         if self.general[i].tickets.solved > 0:
-            tot = self.general[i].tickets.totsolvingtime 
+            tot = self.general[i].tickets.totsolvingtime
             number = self.general[i].tickets.solved
             average = tot / number
-        else: 
+        else:
             average = None
         return dict(
             assigned=self.general[i].tickets.assigned,
@@ -220,9 +226,9 @@ class Stats(MappedClass):
         for entry in self.general:
             cat = entry.category
             i = getElementIndex(entry.commits, language = None)
-            if i is None: 
+            if i is None:
                 n, lines = 0, 0
-            else: 
+            else:
                 n, lines = entry.commits[i].number, entry.commits[i].lines
             if cat != None:
                 cat = TroveCategory.query.get(_id = cat)
@@ -237,7 +243,7 @@ class Stats(MappedClass):
         langlist = []
         by_lang = {}
         i = getElementIndex(self.general, category=None)
-        if i is None: 
+        if i is None:
             return dict(number=0, lines=0)
         return dict([(el.language, dict(lines=el.lines, number=el.number))
                      for el in self.general[i].commits])
@@ -248,21 +254,21 @@ class Stats(MappedClass):
         by_cat = {}
         for entry in self.general:
             cat = entry.category
-            if cat != None: 
+            if cat != None:
                 cat = TroveCategory.query.get(_id = cat)
-            if detailed: 
+            if detailed:
                 by_cat[cat] = entry.messages
             else:
                 i = getElementIndex(entry.messages, messagetype=None)
                 if i is not None:
                     by_cat[cat] = entry.messages[i]
-                else: 
+                else:
                     by_cat[cat] = dict(created=0, modified=0)
         return by_cat
 
     def getArtifactsByType(self, category=None):
         i = getElementIndex(self.general, category = category)
-        if i is None: 
+        if i is None:
             return {}
         entry = self.general[i].messages
         by_type = dict([(el.messagetype, dict(created=el.created,
@@ -287,12 +293,12 @@ class Stats(MappedClass):
             by_cat[cat] = dict(
                 assigned=a,
                 solved=s,
-                revoked=r, 
+                revoked=r,
                 averagesolvingtime=_convertTimeDiff(average))
         return by_cat
 
     def getLastMonthCommits(self, category = None):
-        self.checkOldArtifacts() 
+        self.checkOldArtifacts()
         lineslist = [el.lines for el in self.lastmonth.commits
                      if category in el.categories + [None]]
         return dict(number=len(lineslist), lines=sum(lineslist))
@@ -300,7 +306,7 @@ class Stats(MappedClass):
     def getLastMonthCommitsByCategory(self):
         from allura.model.project import TroveCategory
 
-        self.checkOldArtifacts() 
+        self.checkOldArtifacts()
         seen = set()
         catlist=[el.category for el in self.general
                  if el.category not in seen and not seen.add(el.category)]
@@ -319,7 +325,7 @@ class Stats(MappedClass):
     def getLastMonthCommitsByLanguage(self):
         from allura.model.project import TroveCategory
 
-        self.checkOldArtifacts() 
+        self.checkOldArtifacts()
         seen = set()
         langlist=[el.language for el in self.general
                   if el.language not in seen and not seen.add(el.language)]
@@ -336,13 +342,13 @@ class Stats(MappedClass):
         return by_lang
 
     def getLastMonthArtifacts(self, category = None, art_type = None):
-        self.checkOldArtifacts() 
+        self.checkOldArtifacts()
         cre, mod = reduce(
-            addtuple, 
+            addtuple,
             [(int(el.created),1-int(el.created))
                 for el in self.lastmonth.messages
-                if (category is None or category in el.categories) and 
-                (el.messagetype == art_type or art_type is None)], 
+                if (category is None or category in el.categories) and
+                (el.messagetype == art_type or art_type is None)],
             (0,0))
         return dict(created=cre, modified=mod)
 
@@ -355,7 +361,7 @@ class Stats(MappedClass):
         by_type = {}
         for t in types:
             cre, mod = reduce(
-                addtuple, 
+                addtuple,
                 [(int(el.created),1-int(el.created))
                  for el in self.lastmonth.messages
                  if el.messagetype == t and
@@ -367,7 +373,7 @@ class Stats(MappedClass):
     def getLastMonthArtifactsByCategory(self):
         from allura.model.project import TroveCategory
 
-        self.checkOldArtifacts() 
+        self.checkOldArtifacts()
         seen = set()
         catlist=[el.category for el in self.general
                  if el.category not in seen and not seen.add(el.category)]
@@ -375,9 +381,9 @@ class Stats(MappedClass):
         by_cat = {}
         for cat in catlist:
             cre, mod = reduce(
-                addtuple, 
+                addtuple,
                 [(int(el.created),1-int(el.created))
-                 for el in self.lastmonth.messages 
+                 for el in self.lastmonth.messages
                  if cat in el.categories + [None]], (0,0))
             if cat != None:
                 cat = TroveCategory.query.get(_id = cat)
@@ -393,7 +399,7 @@ class Stats(MappedClass):
         r = len([el for el in self.lastmonth.revokedtickets
                  if category in el.categories + [None]])
         s, time = reduce(
-            addtuple, 
+            addtuple,
             [(1, el.solvingtime)
              for el in self.lastmonth.solvedtickets
              if category in el.categories + [None]],
@@ -407,9 +413,9 @@ class Stats(MappedClass):
         return dict(
             assigned=a,
             revoked=r,
-            solved=s, 
+            solved=s,
             averagesolvingtime=_convertTimeDiff(time))
-        
+
     def getLastMonthTicketsByCategory(self):
         from allura.model.project import TroveCategory
 
@@ -428,17 +434,17 @@ class Stats(MappedClass):
                                         if cat in el.categories+[None]],(0,0))
             if cat != None:
                 cat = TroveCategory.query.get(_id = cat)
-            if s > 0: 
+            if s > 0:
                 time = time / s
             else:
                 time = None
             by_cat[cat] = dict(
                 assigned=a,
                 revoked=r,
-                solved=s, 
+                solved=s,
                 averagesolvingtime=_convertTimeDiff(time))
         return by_cat
-        
+
     def checkOldArtifacts(self):
         now = datetime.utcnow()
         for m in self.lastmonth.messages:
@@ -509,11 +515,11 @@ class Stats(MappedClass):
                 lines = 0
             return lines
 
-        def _addCommitData(stats, topics, languages, lines):          
+        def _addCommitData(stats, topics, languages, lines):
             lt = topics + [None]
             ll = languages + [None]
             for t in lt:
-                i = getElementIndex(stats.general, category=t) 
+                i = getElementIndex(stats.general, category=t)
                 if i is None:
                     newstats = dict(
                         category=t,
@@ -561,14 +567,14 @@ class Stats(MappedClass):
         _addCommitData(self, topics, languages, totlines)
 
         self.lastmonth.commits.append(dict(
-            datetime=commit_datetime, 
-            categories=topics, 
+            datetime=commit_datetime,
+            categories=topics,
             programming_languages=languages,
             lines=totlines))
         self.checkOldArtifacts()
 
     def _updateArtifactsStats(self, art_type, art_datetime, project, action):
-        if action not in ['created', 'modified']: 
+        if action not in ['created', 'modified']:
             return
         topics = [t for t in project.trove_topic if t]
         lt = [None] + topics
@@ -601,7 +607,7 @@ class Stats(MappedClass):
             created=(action == 'created'),
             categories=topics,
             messagetype=art_type))
-        self.checkOldArtifacts() 
+        self.checkOldArtifacts()
 
     def _updateTicketsStats(self, topics, action, s_time = None):
         if action not in ['solved', 'assigned', 'revoked']:
@@ -621,8 +627,8 @@ class Stats(MappedClass):
                     messages=[])
                 self.general.append(stats)
                 i = getElementIndex(self.general, category = t)
-            self.general[i]['tickets'][action] += 1 
-            if action == 'solved': 
+            self.general[i]['tickets'][action] += 1
+            if action == 'solved':
                 self.general[i]['tickets']['totsolvingtime']+=s_time
 
 def getElementIndex(el_list, **kw):
@@ -649,8 +655,8 @@ def _convertTimeDiff(int_seconds):
     minutes = seconds / 60
     seconds = seconds % 60
     return dict(
-        days=days, 
-        hours=hours, 
+        days=days,
+        hours=hours,
         minutes=minutes,
         seconds=seconds)
 


[3/4] git commit: [#6133] remove extremely slow methods using `self.query.find()`

Posted by br...@apache.org.
[#6133] remove extremely slow methods using `self.query.find()`

And remove table displaying these values.  A few other values of this
table (the 'Value' column) could still be displayed, but showing just
one column in a table would look bad, and these values are basically
available from the main table on the stats page anyway.  The methods
for computing those values were left, just unused now.


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/23968ae8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/23968ae8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/23968ae8

Branch: refs/heads/db/6133
Commit: 23968ae839079c56c3196e50c11e23e3bcbc6b12
Parents: 7eb6016
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Sat May 4 22:47:52 2013 -0400
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Sat May 4 22:54:56 2013 -0400

----------------------------------------------------------------------
 Allura/allura/model/stats.py                       |   60 -----------
 .../forgeuserstats/controllers/userstats.py        |   81 ++++-----------
 ForgeUserStats/forgeuserstats/templates/index.html |   44 --------
 3 files changed, 22 insertions(+), 163 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/23968ae8/Allura/allura/model/stats.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/stats.py b/Allura/allura/model/stats.py
index 06ed07d..cff1abc 100644
--- a/Allura/allura/model/stats.py
+++ b/Allura/allura/model/stats.py
@@ -117,66 +117,6 @@ class Stats(MappedClass):
                 return round(float(tickets.solved) / tickets.assigned, 2)
         return 0
 
-    @classmethod
-    def getMaxAndAverageCodeContribution(self):
-        res = self.query.find()
-        n = res.count()
-        if n == 0:
-            return 0, 0
-        values = [x.getCodeContribution() for x in res]
-        maxcontribution=max(values)
-        averagecontribution=sum(values) / n
-        return maxcontribution, round(averagecontribution, 2)
-
-    @classmethod
-    def getMaxAndAverageDiscussionContribution(self):
-        res = self.query.find()
-        n = res.count()
-        if n == 0:
-            return 0, 0
-        values = [x.getDiscussionContribution() for x in res]
-        maxcontribution=max(values)
-        averagecontribution=sum(values)/n
-        return maxcontribution, round(averagecontribution, 2)
-
-    @classmethod
-    def getMaxAndAverageTicketsSolvingPercentage(self):
-        res = self.query.find()
-        n = res.count()
-        if n == 0:
-            return 0, 0
-        values = [x.getTicketsContribution() for x in res]
-        maxcontribution=max(values)
-        averagecontribution=sum(values)/n
-        return maxcontribution, round(averagecontribution, 2)
-
-    def codeRanking(self):
-        res = self.query.find()
-        totn = res.count()
-        if totn == 0:
-            return 0
-        codcontr = self.getCodeContribution()
-        upper = len([x for x in res if x.getCodeContribution() > codcontr])
-        return round((totn - upper) * 100.0 / totn, 2)
-
-    def discussionRanking(self):
-        res = self.query.find()
-        totn = res.count()
-        if totn == 0:
-            return 0
-        disccontr = self.getDiscussionContribution()
-        upper=len([x for x in res if x.getDiscussionContribution()>disccontr])
-        return round((totn - upper) * 100.0 / totn, 2)
-
-    def ticketsRanking(self):
-        res = self.query.find()
-        totn = res.count()
-        if totn == 0:
-            return 0
-        ticketscontr = self.getTicketsContribution()
-        upper=len([x for x in res if x.getTicketsContribution()>ticketscontr])
-        return round((totn - upper) * 100.0 / totn, 2)
-
     def getCommits(self, category = None):
         i = getElementIndex(self.general, category = category)
         if i is None:

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/23968ae8/ForgeUserStats/forgeuserstats/controllers/userstats.py
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/controllers/userstats.py b/ForgeUserStats/forgeuserstats/controllers/userstats.py
index 5b95954..1cb5505 100644
--- a/ForgeUserStats/forgeuserstats/controllers/userstats.py
+++ b/ForgeUserStats/forgeuserstats/controllers/userstats.py
@@ -45,14 +45,14 @@ class ForgeUserStatsCatController(BaseController):
     @with_trailing_slash
     def index(self, **kw):
         self.user = c.project.user_project_of
-        if not self.user: 
+        if not self.user:
             return None
         stats = self.user.stats
         if (not stats.visible) and (c.user != self.user):
             return dict(user=self.user)
-        
+
         cat_id = None
-        if self.category: 
+        if self.category:
             cat_id = self.category._id
         ret_dict = _getDataForCategory(cat_id, stats)
         ret_dict['user'] = self.user
@@ -62,23 +62,23 @@ class ForgeUserStatsCatController(BaseController):
 
 class ForgeUserStatsController(BaseController):
 
-    category = ForgeUserStatsCatController()            
-    
+    category = ForgeUserStatsCatController()
+
     @expose('jinja:forgeuserstats:templates/settings.html')
     @with_trailing_slash
     def settings(self, **kw):
         require_access(c.project, 'admin')
 
         self.user = c.project.user_project_of
-        if not self.user: 
+        if not self.user:
             return dict(user=None)
         if not self.user.stats:
             UserStats.create(self.user)
         return dict(
-            user = self.user, 
+            user = self.user,
             form = StatsPreferencesForm(
                 action = c.project.url() + 'userstats/change_settings'))
-      
+
     @expose()
     @require_post()
     @validate(stats_preferences_form, error_handler=settings)
@@ -86,7 +86,7 @@ class ForgeUserStatsController(BaseController):
         require_access(c.project, 'admin')
 
         self.user = c.project.user_project_of
-        if not self.user: 
+        if not self.user:
             return dict(user=None)
         if not self.user.stats:
             UserStats.create(self.user)
@@ -98,7 +98,7 @@ class ForgeUserStatsController(BaseController):
     @with_trailing_slash
     def index(self, **kw):
         self.user = c.project.user_project_of
-        if not self.user: 
+        if not self.user:
             return dict(user=None)
         if not self.user.stats:
             UserStats.create(self.user)
@@ -131,25 +131,12 @@ class ForgeUserStatsController(BaseController):
         ret_dict['lastmonth_logins'] = stats.getLastMonthLogins()
         ret_dict['categories'] = categories
         days = ret_dict['days']
-        if days >= 30: 
+        if days >= 30:
             ret_dict['permonthlogins'] = \
                 round(stats.tot_logins_count*30.0/days,2)
         else:
             ret_dict['permonthlogins'] = 'n/a'
 
-        ret_dict['codepercentage'] = stats.codeRanking()
-        ret_dict['discussionpercentage'] = stats.discussionRanking()
-        ret_dict['ticketspercentage'] = stats.ticketsRanking()
-        ret_dict['codecontribution'] = stats.getCodeContribution()
-        ret_dict['discussioncontribution'] = stats.getDiscussionContribution()
-        ret_dict['ticketcontribution'] = stats.getTicketsContribution()
-        ret_dict['maxcodecontrib'], ret_dict['averagecodecontrib'] =\
-            stats.getMaxAndAverageCodeContribution()
-        ret_dict['maxdisccontrib'], ret_dict['averagedisccontrib'] =\
-            stats.getMaxAndAverageDiscussionContribution()
-        ret_dict['maxticketcontrib'], ret_dict['averageticketcontrib'] =\
-            stats.getMaxAndAverageTicketsSolvingPercentage()
-        
         return ret_dict
 
 
@@ -157,7 +144,7 @@ class ForgeUserStatsController(BaseController):
     @with_trailing_slash
     def commits(self, **kw):
         self.user = c.project.user_project_of
-        if not self.user: 
+        if not self.user:
             return dict(user=None)
         if not self.user.stats:
             UserStats.create(self.user)
@@ -165,17 +152,17 @@ class ForgeUserStatsController(BaseController):
 
         if (not stats.visible) and (c.user != self.user):
             return dict(user=self.user)
-        
+
         commits = stats.getCommitsByCategory()
         return dict(
             user = self.user,
-            data = commits) 
+            data = commits)
 
     @expose('jinja:forgeuserstats:templates/artifacts.html')
     @with_trailing_slash
     def artifacts(self, **kw):
         self.user = c.project.user_project_of
-        if not self.user: 
+        if not self.user:
             return dict(user=None)
         if not self.user.stats:
             UserStats.create(self.user)
@@ -184,7 +171,7 @@ class ForgeUserStatsController(BaseController):
         if (not stats.visible) and (c.user != self.user):
             return dict(user=self.user)
 
-        stats = self.user.stats       
+        stats = self.user.stats
         artifacts = stats.getArtifactsByCategory(detailed=True)
         return dict(
             user = self.user,
@@ -194,7 +181,7 @@ class ForgeUserStatsController(BaseController):
     @with_trailing_slash
     def tickets(self, **kw):
         self.user = c.project.user_project_of
-        if not self.user: 
+        if not self.user:
             return dict(user=None)
         if not self.user.stats:
             UserStats.create(self.user)
@@ -211,7 +198,7 @@ class ForgeUserStatsController(BaseController):
     @expose()
     def categories_graph(self):
         self.user = c.project.user_project_of
-        if not self.user: 
+        if not self.user:
             return None
 
         categories = {}
@@ -234,39 +221,16 @@ class ForgeUserStatsController(BaseController):
             labels.append(label)
             i += 1
 
-        return create_histogram(data, labels, 
+        return create_histogram(data, labels,
             'Number of projects', 'Projects by category')
 
-    @expose()
-    def code_ranking_bar(self):
-        self.user = c.project.user_project_of
-        if not self.user: 
-            return None
-        stats = self.user.stats
-        return create_progress_bar(stats.codeRanking())
-
-    @expose()
-    def discussion_ranking_bar(self):
-        self.user = c.project.user_project_of
-        if not self.user: 
-            return None
-        stats = self.user.stats
-        return create_progress_bar(stats.discussionRanking())
-
-    @expose()
-    def tickets_ranking_bar(self):
-        self.user = c.project.user_project_of
-        if not self.user: 
-            return None
-        stats = self.user.stats
-        return create_progress_bar(stats.ticketsRanking())
 
 def _getDataForCategory(category, stats):
     totcommits = stats.getCommits(category)
     tottickets = stats.getTickets(category)
     averagetime = tottickets.get('averagesolvingtime')
     artifacts_by_type = stats.getArtifactsByType(category)
-    totartifacts = artifacts_by_type.get(None) 
+    totartifacts = artifacts_by_type.get(None)
     if totartifacts:
         del artifacts_by_type[None]
     else:
@@ -279,7 +243,7 @@ def _getDataForCategory(category, stats):
     averagetime = lm_tickets.get('averagesolvingtime')
 
     days = (datetime.utcnow() - stats.registration_date).days
-    if days >= 30: 
+    if days >= 30:
         pmartifacts = dict(
             created = round(totartifacts['created']*30.0/days,2),
             modified=round(totartifacts['modified']*30.0/days,2))
@@ -297,7 +261,7 @@ def _getDataForCategory(category, stats):
                 round(value['created']*30.0/days,2)
             artifacts_by_type[key]['pmmodified']= \
                 round(value['modified']*30.0/days,2)
-    else: 
+    else:
         pmartifacts = dict(created='n/a', modified='n/a')
         pmcommits = dict(number='n/a', lines='n/a')
         pmtickets = dict(
@@ -322,4 +286,3 @@ def _getDataForCategory(category, stats):
         artifacts_by_type = artifacts_by_type,
         lastmonth_artifacts_by_type = lm_artifacts_by_type,
         permonthtickets = pmtickets)
-

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/23968ae8/ForgeUserStats/forgeuserstats/templates/index.html
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/templates/index.html b/ForgeUserStats/forgeuserstats/templates/index.html
index bc23ec0..2bb6314 100644
--- a/ForgeUserStats/forgeuserstats/templates/index.html
+++ b/ForgeUserStats/forgeuserstats/templates/index.html
@@ -391,50 +391,6 @@
           </p>
         {% endif %}
     {% endif %}
-    {% if not category %}
-      <h2>Overview</h2>
-      <table>
-        <thead>
-          <tr>
-            <th>Field</th>
-            <th>Value</th>
-            <th>Average per-user value</th>
-            <th>Maximum per-user value</th>
-            <th>Rank bar</th>
-          </tr>
-        </thead>
-        <tbody>
-          <tr>
-            <td>Code</td>
-            <td>{{codecontribution}} LOC{% if codecontribution != 1 %}s{% endif %}/month</td>
-            <td>{{averagecodecontrib}} LOC{% if averagecodecontrib != 1 %}s{% endif %}/month</td>
-            <td>{{maxcodecontrib}} LOC{% if maxcodecontrib != 1 %}s{% endif %}/month</td>
-            <td><img src="{{c.project.url()}}userstats/code_ranking_bar"/> {{codepercentage}} %</td>
-          </tr>
-          <tr>
-            <td>Discussion</td>
-            <td>{{discussioncontribution}} contr./month</td>
-            <td>{{averagedisccontrib}} contr./month</td>
-            <td>{{maxdisccontrib}} contr./month</td>
-            <td><img src="{{c.project.url()}}userstats/discussion_ranking_bar"/> {{discussionpercentage}} %</td>
-          </tr>
-          <tr>
-            <td>Solved issues</td>
-            <td>{{ticketcontribution*100}} %</td>
-            <td>{{averageticketcontrib*100}} %</td>
-            <td>{{maxticketcontrib*100}} %</td>
-            <td><img src="{{c.project.url()}}userstats/tickets_ranking_bar"/> {{ticketspercentage}} %</td>
-          </tr>
-        </tbody>
-      </table>
-      <h3>Note</h3>
-      <p>
-         The above table compares the average monthly contribution of this user with the average monthly contributions of the
-         other users of the forge. The progressbar and the percentage refer to the user's position in an overall ranking of the
-         users of this forge. For example, a value of 100% in the field "Code" is associated to the user who has the highest
-         average number of committed LOCs per month. Of course, this doesn't consider the quality of the contributions.
-      </p>
-    {% endif %}
   {% else %}
     {% if user %}
       <h2>Statistics not available</h2>


[2/4] git commit: [#6133] ticket solved values are percentages, so *100

Posted by br...@apache.org.
[#6133] ticket solved values are percentages, so *100


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/7eb60168
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/7eb60168
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/7eb60168

Branch: refs/heads/db/6133
Commit: 7eb60168d7737bc73aaef50be8e9dcd187085c88
Parents: 7c17829
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Sat May 4 22:46:19 2013 -0400
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Sat May 4 22:46:19 2013 -0400

----------------------------------------------------------------------
 ForgeUserStats/forgeuserstats/templates/index.html |   22 +++++++-------
 1 files changed, 11 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/7eb60168/ForgeUserStats/forgeuserstats/templates/index.html
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/templates/index.html b/ForgeUserStats/forgeuserstats/templates/index.html
index ceb3f81..bc23ec0 100644
--- a/ForgeUserStats/forgeuserstats/templates/index.html
+++ b/ForgeUserStats/forgeuserstats/templates/index.html
@@ -45,10 +45,10 @@
           <th>Time interval</th>
         </tr>
       </thead>
-      <tbody> 
+      <tbody>
         <tr>
           <td>Registration date</td>
-          <td>{{registration_date.strftime("%d %b %Y, %H:%M:%S (UTC)")}}</td> 
+          <td>{{registration_date.strftime("%d %b %Y, %H:%M:%S (UTC)")}}</td>
            <td>{{days}} day{% if days != 1 %}s{% endif %} ago</td>
         </tr>
         {% if last_login %}
@@ -187,7 +187,7 @@
             </td>
           {% endif %}
         </tr>
-        
+
         {% for key, value in artifacts_by_type.items() %}
           <tr>
             <td>
@@ -332,7 +332,7 @@
           </td>
           <td>
             {% if tottickets.averagesolvingtime %}
-              {{tottickets.averagesolvingtime.days}} days, 
+              {{tottickets.averagesolvingtime.days}} days,
               {{tottickets.averagesolvingtime.hours}} hours,
               {{tottickets.averagesolvingtime.minutes}} min
             {% else %}n/a{% endif %}
@@ -340,7 +340,7 @@
           <td>n/a</td>
           <td>
             {% if lastmonthtickets.averagesolvingtime %}
-              {{lastmonthtickets.averagesolvingtime.days}} days, 
+              {{lastmonthtickets.averagesolvingtime.days}} days,
               {{lastmonthtickets.averagesolvingtime.hours}} hours,
               {{lastmonthtickets.averagesolvingtime.minutes}} min
             {% else %}n/a{% endif %}
@@ -381,7 +381,7 @@
             {% endfor %}
           </tbody>
         </table>
-         
+
         {% if categories|length > 1 %}
           <p>
             The same data listed in the previous table is graphically presented by the following histogram.
@@ -420,9 +420,9 @@
           </tr>
           <tr>
             <td>Solved issues</td>
-            <td>{{ticketcontribution}} %</td>
-            <td>{{averageticketcontrib}} %</td>
-            <td>{{maxticketcontrib}} %</td>
+            <td>{{ticketcontribution*100}} %</td>
+            <td>{{averageticketcontrib*100}} %</td>
+            <td>{{maxticketcontrib*100}} %</td>
             <td><img src="{{c.project.url()}}userstats/tickets_ranking_bar"/> {{ticketspercentage}} %</td>
           </tr>
         </tbody>
@@ -438,13 +438,13 @@
   {% else %}
     {% if user %}
       <h2>Statistics not available</h2>
-      <div class="grid-20"> 
+      <div class="grid-20">
         This user has set his or her preferences so that personal statistics are not visible
         to other users of the forge.
       </div>
     {% else %}
       <h2>Invalid user</h2>
-      <div class="grid-20"> 
+      <div class="grid-20">
         You are looking for personal statistics of a user which doesn't exist on this forge. Check your url.
       </div>
     {% endif %}


[4/4] git commit: [#6133] remove histogram, and matplotlib & numpy dependences

Posted by br...@apache.org.
[#6133] remove histogram, and matplotlib & numpy dependences

Only remaining use of matplotlib was a histogram (bar chart)
of a user's projects per trove category.  This is a simple chart
and the data is available in a table, so not worth the very big
and complex dependencies of matplotlib and numpy and associated
workarounds due to them.  So removing the histogram, dependencies,
and workarounds.


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/42eb9932
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/42eb9932
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/42eb9932

Branch: refs/heads/db/6133
Commit: 42eb99325eb3a4ab678634ed28949b612bcfa2e7
Parents: 23968ae
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Sat May 4 23:03:06 2013 -0400
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Sat May 4 23:03:06 2013 -0400

----------------------------------------------------------------------
 Allura/allura/lib/graphics/__init__.py             |   16 ---
 Allura/allura/lib/graphics/graphic_methods.py      |   86 ---------------
 Allura/docs/conf.py                                |   25 ----
 .../forgeuserstats/controllers/userstats.py        |   30 -----
 ForgeUserStats/forgeuserstats/templates/index.html |    9 --
 requirements-common.txt                            |    2 -
 vagrant/manifests/ubuntu-1204-server-amd64.pp      |   14 ---
 7 files changed, 0 insertions(+), 182 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/42eb9932/Allura/allura/lib/graphics/__init__.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/graphics/__init__.py b/Allura/allura/lib/graphics/__init__.py
deleted file mode 100644
index 144e298..0000000
--- a/Allura/allura/lib/graphics/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-#       Licensed to the Apache Software Foundation (ASF) under one
-#       or more contributor license agreements.  See the NOTICE file
-#       distributed with this work for additional information
-#       regarding copyright ownership.  The ASF licenses this file
-#       to you under the Apache License, Version 2.0 (the
-#       "License"); you may not use this file except in compliance
-#       with the License.  You may obtain a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#       Unless required by applicable law or agreed to in writing,
-#       software distributed under the License is distributed on an
-#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-#       KIND, either express or implied.  See the License for the
-#       specific language governing permissions and limitations
-#       under the License.

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/42eb9932/Allura/allura/lib/graphics/graphic_methods.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/graphics/graphic_methods.py b/Allura/allura/lib/graphics/graphic_methods.py
deleted file mode 100644
index 777cfc0..0000000
--- a/Allura/allura/lib/graphics/graphic_methods.py
+++ /dev/null
@@ -1,86 +0,0 @@
-#       Licensed to the Apache Software Foundation (ASF) under one
-#       or more contributor license agreements.  See the NOTICE file
-#       distributed with this work for additional information
-#       regarding copyright ownership.  The ASF licenses this file
-#       to you under the Apache License, Version 2.0 (the
-#       "License"); you may not use this file except in compliance
-#       with the License.  You may obtain a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#       Unless required by applicable law or agreed to in writing,
-#       software distributed under the License is distributed on an
-#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-#       KIND, either express or implied.  See the License for the
-#       specific language governing permissions and limitations
-#       under the License.
-
-import StringIO
-
-from matplotlib.backends.backend_agg import FigureCanvasAgg
-from matplotlib.figure import Figure
-import Image
-
-
-def create_histogram(data, tick_labels, y_label, title):
-    fig = Figure(figsize=(10,5), dpi=80, facecolor='white')
-    ax = fig.add_subplot(111, axisbg='#EEEEFF')
-
-    canvas = FigureCanvasAgg(fig)
-    n, bins, patches = ax.hist(data, facecolor='#330099', edgecolor='white')
-    ax.set_ylabel(y_label)
-    ax.set_title(title)
-
-    ax.set_xticks(range(len(tick_labels)+1))
-    ax.get_xaxis().set_ticklabels(tick_labels, rotation=45, va='top', ha='right')
-    ax.get_xaxis().set_ticks_position('none')
-    ax.set_autoscalex_on(False)
-
-    ax.set_xlim((-1, len(tick_labels)))
-    ax.set_ylim((0, 1+max([data.count(el) for el in data])))
-    fig.subplots_adjust(bottom=0.3)
-
-    canvas.draw()
-
-    s = canvas.tostring_rgb()
-    l,b,w,h = fig.bbox.bounds
-    w, h = int(w), int(h)
-
-    output = StringIO.StringIO()
-    im = Image.fromstring( "RGB", (w,h), s)
-    im.save(output, 'PNG')
-
-    return output.getvalue()
-
-def create_progress_bar(value):
-    value = value / 100.0
-    if value < 1 / 5.0:
-        color = 'red'
-    elif value < 2 / 5.0:
-        color = 'orange'
-    elif value < 3 / 5.0:
-        color = 'yellow'
-    elif value < 4 / 5.0:
-        color = 'lightgreen'
-    else:
-        color = 'green'
-
-    fig = Figure(figsize=(3,0.5), dpi=40, facecolor='gray')
-    canvas = FigureCanvasAgg(fig)
-    canvas.draw()
-
-    from matplotlib.patches import Rectangle
-    from matplotlib.axes import Axes
-
-    fig.draw_artist(Rectangle((0,0), int(value * 120), 20, color=color))
-    fig.draw_artist(Rectangle((1,0), 119, 19, fill=False, ec='black'))
-
-    l,b,w,h = fig.bbox.bounds
-    s = canvas.tostring_rgb()
-    w, h = int(w), int(h)
-
-    output = StringIO.StringIO()
-    im = Image.fromstring( "RGB", (w,h), s)
-    im.save(output, 'PNG')
-
-    return output.getvalue()

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/42eb9932/Allura/docs/conf.py
----------------------------------------------------------------------
diff --git a/Allura/docs/conf.py b/Allura/docs/conf.py
index 81c0e1f..f7d8757 100644
--- a/Allura/docs/conf.py
+++ b/Allura/docs/conf.py
@@ -30,31 +30,6 @@
 
 import sys, os
 
-class Mock(object):
-    def __init__(self, *args, **kwargs):
-        pass
-
-    def __call__(self, *args, **kwargs):
-        return Mock()
-
-    @classmethod
-    def __getattr__(cls, name):
-        if name in ('__file__', '__path__'):
-            return '/dev/null'
-        elif name[0] == name[0].upper():
-            mockType = type(name, (), {})
-            mockType.__module__ = __name__
-            return mockType
-        else:
-            return Mock()
-
-MOCK_MODULES = ['matplotlib', 'matplotlib.axes',
-        'matplotlib.backends', 'matplotlib.backends.backend_agg',
-        'matplotlib.figure', 'matplotlib.patches']
-
-for mod_name in MOCK_MODULES:
-    sys.modules[mod_name] = Mock()
-
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
 # documentation root, use os.path.abspath to make it absolute, like shown here.

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/42eb9932/ForgeUserStats/forgeuserstats/controllers/userstats.py
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/controllers/userstats.py b/ForgeUserStats/forgeuserstats/controllers/userstats.py
index 1cb5505..85b26df 100644
--- a/ForgeUserStats/forgeuserstats/controllers/userstats.py
+++ b/ForgeUserStats/forgeuserstats/controllers/userstats.py
@@ -20,7 +20,6 @@ from tg.decorators import with_trailing_slash
 from datetime import datetime
 from allura.controllers import BaseController
 import allura.model as M
-from allura.lib.graphics.graphic_methods import create_histogram, create_progress_bar
 from forgeuserstats.model.stats import UserStats
 from pylons import tmpl_context as c
 from allura.lib.security import require_access
@@ -195,35 +194,6 @@ class ForgeUserStatsController(BaseController):
             user=self.user,
             data=artifacts)
 
-    @expose()
-    def categories_graph(self):
-        self.user = c.project.user_project_of
-        if not self.user:
-            return None
-
-        categories = {}
-        for p in self.user.my_projects():
-            for cat in p.trove_topic:
-                cat = M.TroveCategory.query.get(_id = cat)
-                if categories.get(cat):
-                    categories[cat] += 1
-                else:
-                    categories[cat] = 1
-        data = []
-        labels = []
-        i = 0
-        for cat in sorted(categories.keys(), key=lambda x:x.fullname):
-            n = categories[cat]
-            data = data + [i] * n
-            label = cat.fullname
-            if len(label) > 15:
-                label = label[:15] + "..."
-            labels.append(label)
-            i += 1
-
-        return create_histogram(data, labels,
-            'Number of projects', 'Projects by category')
-
 
 def _getDataForCategory(category, stats):
     totcommits = stats.getCommits(category)

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/42eb9932/ForgeUserStats/forgeuserstats/templates/index.html
----------------------------------------------------------------------
diff --git a/ForgeUserStats/forgeuserstats/templates/index.html b/ForgeUserStats/forgeuserstats/templates/index.html
index 2bb6314..406fb20 100644
--- a/ForgeUserStats/forgeuserstats/templates/index.html
+++ b/ForgeUserStats/forgeuserstats/templates/index.html
@@ -381,15 +381,6 @@
             {% endfor %}
           </tbody>
         </table>
-
-        {% if categories|length > 1 %}
-          <p>
-            The same data listed in the previous table is graphically presented by the following histogram.
-          </p>
-          <p>
-            <img src="{{c.project.url()}}userstats/categories_graph"/>
-          </p>
-        {% endif %}
     {% endif %}
   {% else %}
     {% if user %}

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/42eb9932/requirements-common.txt
----------------------------------------------------------------------
diff --git a/requirements-common.txt b/requirements-common.txt
index 75f4541..21ea929 100644
--- a/requirements-common.txt
+++ b/requirements-common.txt
@@ -47,8 +47,6 @@ TurboGears2==2.1.5
 WebOb==1.0.8
 # part of the stdlib, but with a version number.  see http://guide.python-distribute.org/pip.html#listing-installed-packages
 wsgiref==0.1.2
-numpy==1.6.1
-matplotlib==1.1.1
 
 # tg2 deps (not used directly)
 Babel==0.9.6

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/42eb9932/vagrant/manifests/ubuntu-1204-server-amd64.pp
----------------------------------------------------------------------
diff --git a/vagrant/manifests/ubuntu-1204-server-amd64.pp b/vagrant/manifests/ubuntu-1204-server-amd64.pp
index 1feb18e..4031084 100644
--- a/vagrant/manifests/ubuntu-1204-server-amd64.pp
+++ b/vagrant/manifests/ubuntu-1204-server-amd64.pp
@@ -107,19 +107,6 @@ file { '/home/vagrant/src/allura':
   require => [ File['/home/vagrant/src'], Exec['clone repo'] ],
 }
 
-# HACK to get numpy installed in the venv before installing
-# remaining dependencies via requirements file
-exec { "pip install numpy":
-  command => "/home/vagrant/env-allura/bin/pip install numpy==1.6.1",
-  cwd     => "/vagrant/allura",
-  timeout => 0,
-  logoutput => true,
-  returns => 0,
-  tries => 3,
-  require => [ Exec[ "clone repo"], Exec[ "create allura venv" ],
-               ],
-}
-
 # install Allura dependencies
 exec { "pip install":
   command => "/home/vagrant/env-allura/bin/pip install -r requirements.txt",
@@ -132,7 +119,6 @@ exec { "pip install":
   tries => 3,
   require => [ Exec[ "clone repo"], Exec[ "create allura venv" ],
                File["/usr/lib/libjpeg.so"], File["/usr/lib/libz.so"],
-               Exec["pip install numpy"],
                ],
 }