Optimizations in pygit statistics. Switch to using ModelForm for BugForm. Bugfixes.

portnov [2008-06-16 15:20:25]
Optimizations in pygit statistics. Switch to using ModelForm for BugForm. Bugfixes.
Filename
mgmt/bugs_views.py
mgmt/forms.py
mgmt/project_views.py
pygit/decorators.py
pygit/pygit.py
diff --git a/mgmt/bugs_views.py b/mgmt/bugs_views.py
index 66b3454..9443f96 100644
--- a/mgmt/bugs_views.py
+++ b/mgmt/bugs_views.py
@@ -15,31 +15,20 @@ def bug_report(request,pid):
   if request.method=='POST':
     form = BugForm(request.POST)
     if form.is_valid():
-      name = form.cleaned_data['name']
-      comp = form.cleaned_data['component']
-      actions = form.cleaned_data['your_actions']
-      expected = form.cleaned_data['expected']
-      unexpected = form.cleaned_data['unexpected']
-      text  = form.cleaned_data['text']
       s0 = BugState.objects.get(pk=1)
-      b = Bug(created=datetime.now(),
-          author = request.user,
-          project = project,
-          status = s0,
-          name = name,
-          component=comp,
-          actions=actions,
-          expected=expected,
-          unexpected=unexpected,
-          priority=-1,
-          text = text)
-      b.save()
+      bug = form.save(commit=False)
+      bug.created = datetime.now()
+      bug.author = request.user
+      bug.status = s0
+      bug.priority = -1
+      bug.save()
       return HttpResponseRedirect(reverse('mgmt.views.project_bugs',args=(pid,)))
     else:
       return {'project': project, 'form': form}
-  form = BugForm()
-  return {'project': project,
-       'form': form}
+  else:
+    form = BugForm()
+    return {'project': project,
+         'form': form}

 @render_to('bug.html')
 def one_bug(request,id):
@@ -121,30 +110,17 @@ def one_bug(request,id):
 @render_to('edit_bug.html')
 def edit_bug(request,bug):
   if request.method=='POST':
-    form = BugForm(request.POST)
+    form = BugForm(request.POST,instance=bug)
     if form.is_valid():
-      name = form.cleaned_data['name']
-      text = form.cleaned_data['text']
-      comp = form.cleaned_data['component']
-      actions = form.cleaned_data['your_actions']
-      expected = form.cleaned_data['expected']
-      unexpected = form.cleaned_data['unexpected']
-      bug.name = name
-      bug.text = text
-      bug.component = comp
-      bug.actions = actions
-      bug.expected = expected
-      bug.unexpected = unexpected
-      bug.save()
-  form = BugForm({'name': bug.name,
-                  'text': bug.text,
-                  'component': bug.component,
-                  'your_actions': bug.actions,
-                  'expected': bug.expected,
-                  'unexpected': bug.unexpected})
-  return {'project': bug.project,
-       'bug': bug,
-       'form': form}
+      bug = form.save()
+      return HttpResponseRedirect(reverse('mgmt.views.one_bug',args=(bug.id,)))
+    else:
+      return {'project': bug.project, 'bug': bug, 'form': form }
+  else:
+    form = BugForm(instance=bug)
+    return {'project': bug.project,
+         'bug': bug,
+         'form': form}

 @render_to('all_bugs.html')
 def all_bugs(request):
diff --git a/mgmt/forms.py b/mgmt/forms.py
index 0861f26..78f4411 100644
--- a/mgmt/forms.py
+++ b/mgmt/forms.py
@@ -13,13 +13,16 @@ class CommentForm(forms.Form):
   title = forms.CharField(required=False,label=u'Тема')
   text = forms.CharField(widget=forms.Textarea(),label=u'Текст')

-class BugForm(forms.Form):
+class BugForm(forms.ModelForm):
   name = forms.CharField(label=u'Название')
   component = forms.CharField(required=False,label=u'Компонент')
-  your_actions = forms.CharField(widget=forms.Textarea(),label=u'Ваши действия')
+  actions = forms.CharField(widget=forms.Textarea(),label=u'Ваши действия')
   expected = forms.CharField(widget=forms.Textarea(),label=u'Что ожидали получить')
   unexpected = forms.CharField(widget=forms.Textarea(),label=u'Что получили')
   text = forms.CharField(widget=forms.Textarea(),label=u'Дополнения')
+  class Meta:
+    model = Bug
+    exclude = ("created","author",'project','confirmed','responsible','status','fixed')

 class BugPriorityForm(forms.Form):
   priority = forms.ChoiceField(settings.PRIORITY_CHOICES,required=False)
@@ -39,10 +42,6 @@ class DocForm(forms.ModelForm):
     model = Document
     exclude = ("created", "author")

-# class DocForm(forms.Form):
-#   name = forms.CharField()
-#   text = forms.CharField(widget=forms.Textarea())
-
 class MessageForm(forms.Form):
   name = forms.CharField()
   text = forms.CharField(widget=forms.Textarea())
diff --git a/mgmt/project_views.py b/mgmt/project_views.py
index 192710e..029109f 100644
--- a/mgmt/project_views.py
+++ b/mgmt/project_views.py
@@ -36,7 +36,7 @@ def one_project(request,project):
 @check_auth(Project,'view')
 @render_to('project_bugs.html')
 def project_bugs(request,project):
-  page,pages,bugs = get_bugs(request,id)
+  page,pages,bugs = get_bugs(request,project.id)
   for bug in bugs:
     bug.complexity_str = dict(settings.COMPLEXITY_CHOICES).get(bug.complexity,'Unknown')
     bug.priority_str = dict(settings.PRIORITY_CHOICES).get(bug.priority,'Unset')
diff --git a/pygit/decorators.py b/pygit/decorators.py
new file mode 100644
index 0000000..e03c556
--- /dev/null
+++ b/pygit/decorators.py
@@ -0,0 +1,11 @@
+
+def count(func):
+  def wrapper(*args,**kwargs):
+    f = open('/home/portnov/www/projects/count.log','a')
+    f.write(func.__name__+'\n')
+    f.close()
+    return func(*args,**kwargs)
+  wrapper.__name__ = func.__name__
+  return wrapper
+
+count = lambda f: f
diff --git a/pygit/pygit.py b/pygit/pygit.py
index 0edb26e..435449b 100644
--- a/pygit/pygit.py
+++ b/pygit/pygit.py
@@ -7,41 +7,51 @@ from git import *
 from django.conf import settings
 from django.core.cache import cache

+from decorators import count
+
 rp = None
 curr_path = None

+@count
 def open_repo(rid):
   global curr_path,rp
   path = settings.REPOS[int(rid)]
-#   if rp and curr_path==path:
-#     return rp
+  if rp and curr_path==path:
+    return rp
   curr_path = path
   rp = Repo(path)
   return rp

+@count
 def files(tree):
   contents = tree.contents
   return [(blob.id,blob.name) for blob in contents if blob.__class__.__name__=='Blob']

+@count
 def dirs(tree):
   contents = tree.contents
   return [(tree.id,tree.name) for tree in contents if tree.__class__.__name__=='Tree']

+@count
 def repos():
   return [(i,basename(settings.REPOS[i])) for i in range(len(settings.REPOS))]

+@count
 def description(rid):
   r = open_repo(rid)
   return r.description

+@count
 def branches(rid):
   r = open_repo(rid)
   return [b.name for b in r.branches]

+@count
 def tags(rid):
   r = open_repo(rid)
   return [t.name for t in r.tags]

+@count
 def date(tp):
   dt = time.localtime(time.mktime(tp)-time.altzone)
   return time.strftime("%d.%m.%Y %H:%M:%S", dt)
@@ -58,11 +68,13 @@ def tarball(rid,branch):
     f.close()
   return path

+@count
 def commits(rid,branch='master',n=10):
   r = open_repo(rid)
   cs = r.commits(branch,max_count=n)
   return [(c.id_abbrev,date(c.authored_date),c.author.name,c.message) for c in cs]

+@count
 def root_tree(rid,branch='master'):
   r = open_repo(rid)
   t = r.tree()
@@ -70,6 +82,7 @@ def root_tree(rid,branch='master'):
   fs = files(t)
   return ds,fs

+@count
 def tree(rid,tid):
   r = open_repo(rid)
   t = r.tree(tid)
@@ -80,9 +93,11 @@ def blame(rid,file,branch='master'):
   bl = Blob.blame(r,branch,file)
   return [(ci.id_abbrev,ci.author.name,date(ci.authored_date),ci.message[:40],''.join(l[:40])) for ci,l in bl]

+@count
 def cached_diff(repo,c1,c2):
   return Commit.diff(repo,c1,c2)

+@count
 def diff_all(rid,cid1,cid2=None):
   r = open_repo(rid)
   c1 = r.commits(cid1)[0]
@@ -96,6 +111,7 @@ def diff_all(rid,cid1,cid2=None):
   ds = cached_diff(r,c2,c1)
   return [(d.a_path,d.diff) for d in ds]

+@count
 def diff_path(rid,path,cid1,cid2=None):
   r = open_repo(rid)
   c1 = r.commits(cid1)[0]
@@ -109,6 +125,7 @@ def diff_path(rid,path,cid1,cid2=None):
   ds = cached_diff(r,c2,c1)
   return [(d.a_path,d.diff) for d in ds if d.a_path==path]

+@count
 def group_by_date(lst):
   "[Commit] -> [(date,Commit)]"
   def date(tp):
@@ -118,46 +135,44 @@ def group_by_date(lst):
   d.sort()
   d = [(date(e[0]),e[1]) for e in d]
   prev = d[0][0]
-  group = []
   r = []
+  st = dict(lines=0,files=0,insertions=0,deletions=0)
+  count = 0
   for dt,cm in d:
-    if dt == prev:
-      group.append(cm)
-    else:
-      r.append((prev,group))
-      del group
-      group = []
-    prev = dt
-  r.append((prev,group))
-  return r
-
-def stats_sum(lst):
-  "[Commit] -> dict(lines=?, files=?)"
-  r = {'lines': 0, 'files': 0,'insertions':0, 'deletions':0}
-  for cm in lst:
     try:
-      r['lines'] += cm.stats.total['lines']
-      r['files'] += cm.stats.total['files']
-      r['insertions'] += cm.stats.total['insertions']
-      r['deletions'] += cm.stats.total['deletions']
-    except ValueError:
+      c_stats = cm.stats.total # Sometimes GitPython raises ValueError here
+    except ValueError:
       pass
+    else:
+      if dt == prev:
+        count += 1
+        st['lines'] += c_stats['lines']
+        st['files'] += c_stats['files']
+        st['insertions'] += c_stats['insertions']
+        st['deletions'] += c_stats['deletions']
+      else:
+        r.append((prev,count,st))
+        st = dict(lines=0,files=0,insertions=0,deletions=0)
+        count = 1
+      prev = dt
+  r.append((prev,count,st))
   return r

+@count
 def commits_stats(rid,branch='master'):
   r = open_repo(rid)
   d = r.commits(branch,max_count=200)
   grp = group_by_date(d)
-  print [(g[0],[c.message for c in g[1]]) for g in grp]
   dates = [g[0] for g in grp]
-  n_commits = [len(g[1]) for g in grp]
-  stats = [stats_sum(g[1]) for g in grp]
+  n_commits = [g[1] for g in grp]
+  stats = [g[2] for g in grp]
   files = [s['files'] for s in stats]
   lines = [s['lines'] for s in stats]
   inss  = [s['insertions'] for s in stats]
   dels  = [s['deletions'] for s in stats]
   return dates,n_commits,files,lines,inss,dels

+@count
 def commit_stats(rid,cid):
   r = open_repo(rid)
   c = r.commit(cid)
@@ -166,11 +181,13 @@ def commit_stats(rid,cid):
   except ValueError: # This is a bug in GitPython
     return {'files':0, 'insertions':0,'deletions':0,'lines':0}, {}

+@count
 def commit_message(rid,cid):
   r = open_repo(rid)
   c = r.commit(cid)
   return c.message

+@count
 def commit(rid,cid):
   r = open_repo(rid)
   return r.commit(cid)
ViewGit