You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by ac...@apache.org on 2012/12/27 20:01:24 UTC
[1/8] [#5518] Initial version of Bitergia Metrics product integrated
inside Allura. Still several issued need to be polished.
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/b129d544/AlluraBitergiaMetrics/bitergiametrics/tasks.py
----------------------------------------------------------------------
diff --git a/AlluraBitergiaMetrics/bitergiametrics/tasks.py b/AlluraBitergiaMetrics/bitergiametrics/tasks.py
new file mode 100644
index 0000000..b0098b1
--- /dev/null
+++ b/AlluraBitergiaMetrics/bitergiametrics/tasks.py
@@ -0,0 +1,17 @@
+import logging
+
+from pylons import c
+from allura.lib.decorators import task
+
+log = logging.getLogger(__name__)
+
+@task
+def launch_bicho(shortname):
+ log.info("TASK: Launching Bicho tool", shortname);
+# from forgediscussion import model as DM
+# forum = DM.Forum.query.get(
+# shortname=shortname, app_config_id=c.app.config._id)
+# if forum is None:
+# log.error("Error looking up forum: %r", shortname)
+# return
+# forum.update_stats()
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/b129d544/AlluraBitergiaMetrics/bitergiametrics/templates/__init__.py
----------------------------------------------------------------------
diff --git a/AlluraBitergiaMetrics/bitergiametrics/templates/__init__.py b/AlluraBitergiaMetrics/bitergiametrics/templates/__init__.py
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/b129d544/AlluraBitergiaMetrics/bitergiametrics/templates/metrics/bicho.html
----------------------------------------------------------------------
diff --git a/AlluraBitergiaMetrics/bitergiametrics/templates/metrics/bicho.html b/AlluraBitergiaMetrics/bitergiametrics/templates/metrics/bicho.html
new file mode 100644
index 0000000..fe174e2
--- /dev/null
+++ b/AlluraBitergiaMetrics/bitergiametrics/templates/metrics/bicho.html
@@ -0,0 +1,19 @@
+{% extends g.theme.master %}
+{% block title %}
+ {{c.project.name}} / {{c.app.config.options.mount_label}}
+{% endblock %}
+{% block header%}
+ {{c.project.name}} / {{c.app.config.options.mount_label}}:
+ Bitergia Bicho Tool Config
+{% endblock %}
+
+{% block content %}
+
+<form method="get">
+Now <input type="checkbox" name="when" value="now" checked>
+<input type=submit value="Launch bicho">
+</form>
+
+When: {{when}}
+
+{% endblock %}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/b129d544/AlluraBitergiaMetrics/bitergiametrics/templates/metrics/index.html
----------------------------------------------------------------------
diff --git a/AlluraBitergiaMetrics/bitergiametrics/templates/metrics/index.html b/AlluraBitergiaMetrics/bitergiametrics/templates/metrics/index.html
new file mode 100644
index 0000000..9366036
--- /dev/null
+++ b/AlluraBitergiaMetrics/bitergiametrics/templates/metrics/index.html
@@ -0,0 +1,20 @@
+{% extends g.theme.master %}
+
+{% do g.register_app_css('metrics.css', compress=False) %}
+
+{% block title %}{{c.project.name}} / {{c.app.config.options.mount_label}}{% endblock %}
+
+{% block header %}{{c.project.name}} / {{c.app.config.options.mount_label}}{% endblock %}
+
+{% block content %}
+
+<p><h1>Allura Metrics</h1></p>
+
+<p>
+Proof of concept of how some parameters of the evolution of a software project can be visualized.
+Allura integation. Visualization is still preliminary and incomplete.
+</p>
+<div align=right>
+Powered by <a href="http://www.bitergia.com"><img src="{{g.app_static('bitergia-logo-peq.png')}}" border=0></a>
+</div>
+{% endblock %}
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/b129d544/AlluraBitergiaMetrics/bitergiametrics/templates/metrics/its_milestone0.html
----------------------------------------------------------------------
diff --git a/AlluraBitergiaMetrics/bitergiametrics/templates/metrics/its_milestone0.html b/AlluraBitergiaMetrics/bitergiametrics/templates/metrics/its_milestone0.html
new file mode 100644
index 0000000..1014a4b
--- /dev/null
+++ b/AlluraBitergiaMetrics/bitergiametrics/templates/metrics/its_milestone0.html
@@ -0,0 +1,37 @@
+{% extends g.theme.master %}
+
+{% do g.register_app_css('vizgrimoire.css', compress=False) %}
+{% block title %}{{c.project.name}} / {{c.app.config.options.mount_label}}{% endblock %}
+
+{% block header %}{{c.project.name}} / {{c.app.config.options.mount_label}}: Tickets{% endblock %}
+
+{% block content %}
+
+ <script type="text/javascript" src="{{g.app_static('jquery-1.7.1.min.js')}}"></script>
+
+ <div align=center>
+ <a href="{{g.app_static('allura/data/json/its-milestone0.json')}}">Tickets</a>
+ </div>
+
+ <div>
+ <div style="float:right">
+ <h1>ENVISION</h1>
+ <div id="its-envision"></div>
+ </div>
+ <div>
+ <div id="its-open-flotr2" style="width:200px;height:200px"></div>
+ <div id="its-openers-flotr2" style="width:200px;height:200px"></div>
+ <div id="its-closed-flotr2" style="width:200px;height:200px"></div>
+ <div id="its-closers-flotr2" style="width:200px;height:200px"></div>
+ </div>
+ </div>
+
+ <div id="report-config" data-its-data-file="{{g.app_static('allura/data/json/its-milestone0.json')}}"></div>
+
+ <div align=right>
+ Powered by <a href="http://www.bitergia.com"><img src="{{g.app_static('bitergia-logo-peq.png')}}" border=0></a>
+ </div>
+
+ <script type="text/javascript" src="{{g.app_static('vizgrimoire.min.js')}}"></script>
+
+{% endblock %}
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/b129d544/AlluraBitergiaMetrics/bitergiametrics/templates/metrics/scm_milestone0.html
----------------------------------------------------------------------
diff --git a/AlluraBitergiaMetrics/bitergiametrics/templates/metrics/scm_milestone0.html b/AlluraBitergiaMetrics/bitergiametrics/templates/metrics/scm_milestone0.html
new file mode 100644
index 0000000..e59dbca
--- /dev/null
+++ b/AlluraBitergiaMetrics/bitergiametrics/templates/metrics/scm_milestone0.html
@@ -0,0 +1,37 @@
+{% extends g.theme.master %}
+
+{% do g.register_app_css('vizgrimoire.css', compress=False) %}
+{% block title %}{{c.project.name}} / {{c.app.config.options.mount_label}}{% endblock %}
+
+{% block header %}
+ {{c.project.name}} / {{c.app.config.options.mount_label}}: Source code
+{% endblock %}
+
+{% block content %}
+ <script type="text/javascript" src="{{g.app_static('jquery-1.7.1.min.js')}}"></script>
+
+ <div align=center>
+ <a href="{{g.app_static('allura/data/json/scm-milestone0.json')}}">SCM Data: Commits vs Committers!</a>
+ </div>
+
+ <div>
+ <div style="float:right">
+ <h1>ENVISION</h1>
+ <div id="scm-envision"></div>
+ </div>
+ <div>
+ <div id="scm-commits-flotr2" style="width:200px;height:200px"></div>
+ <div id="scm-committers-flotr2" style="width:200px;height:200px"></div>
+ <div id="scm-files-flotr2" style="width:200px;height:200px"></div>
+ <div id="scm-branches-flotr2" style="width:200px;height:200px"></div>
+ </div>
+ </div>
+
+ <div id="report-config" data-scm-data-file="{{g.app_static('allura/data/json/scm-milestone0.json')}}"></div>
+
+ <div align=right>
+ Powered by <a href="http://www.bitergia.com"><img src="{{g.app_static('bitergia-logo-peq.png')}}" border=0></a>
+ </div>
+
+ <script type="text/javascript" src="{{g.app_static('vizgrimoire.min.js')}}"></script>
+{% endblock %}
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/b129d544/AlluraBitergiaMetrics/bitergiametrics/templates/metrics_widgets/__init__.py
----------------------------------------------------------------------
diff --git a/AlluraBitergiaMetrics/bitergiametrics/templates/metrics_widgets/__init__.py b/AlluraBitergiaMetrics/bitergiametrics/templates/metrics_widgets/__init__.py
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/b129d544/AlluraBitergiaMetrics/bitergiametrics/templates/metrics_widgets/view_metrics.html
----------------------------------------------------------------------
diff --git a/AlluraBitergiaMetrics/bitergiametrics/templates/metrics_widgets/view_metrics.html b/AlluraBitergiaMetrics/bitergiametrics/templates/metrics_widgets/view_metrics.html
new file mode 100644
index 0000000..7289713
--- /dev/null
+++ b/AlluraBitergiaMetrics/bitergiametrics/templates/metrics_widgets/view_metrics.html
@@ -0,0 +1,8 @@
+{% import 'allura:templates/jinja_master/lib.html' as lib with context %}
+
+{{value.html_text|safe}}
+{{lib.related_artifacts(value)}}
+<em class="grid-19">
+Showing METRICS for the project
+</em>
+
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/b129d544/AlluraBitergiaMetrics/bitergiametrics/tests/__init__.py
----------------------------------------------------------------------
diff --git a/AlluraBitergiaMetrics/bitergiametrics/tests/__init__.py b/AlluraBitergiaMetrics/bitergiametrics/tests/__init__.py
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/b129d544/AlluraBitergiaMetrics/bitergiametrics/tests/functional/__init__.py
----------------------------------------------------------------------
diff --git a/AlluraBitergiaMetrics/bitergiametrics/tests/functional/__init__.py b/AlluraBitergiaMetrics/bitergiametrics/tests/functional/__init__.py
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/b129d544/AlluraBitergiaMetrics/bitergiametrics/tests/functional/test_root.py
----------------------------------------------------------------------
diff --git a/AlluraBitergiaMetrics/bitergiametrics/tests/functional/test_root.py b/AlluraBitergiaMetrics/bitergiametrics/tests/functional/test_root.py
new file mode 100644
index 0000000..4f6a4b1
--- /dev/null
+++ b/AlluraBitergiaMetrics/bitergiametrics/tests/functional/test_root.py
@@ -0,0 +1,175 @@
+import datetime
+
+from ming.orm.ormsession import ThreadLocalORMSession
+
+from alluratest.controller import TestController
+from allura import model as M
+
+#---------x---------x---------x---------x---------x---------x---------x
+# RootController methods exposed:
+# index, new_page, search
+# PageController methods exposed:
+# index, edit, history, diff, raw, revert, update
+# CommentController methods exposed:
+# reply, delete
+
+class TestRootController(TestController):
+
+ def _post(self, slug='', **kw):
+ d = {
+ 'title':'My Post',
+ 'text':'Nothing to see here',
+ 'labels':'',
+ 'state':'published'}
+ d.update(kw)
+ r = self.app.post('/blog%s/save' % slug, params=d)
+ return r
+
+ def _blog_date(self):
+ return datetime.datetime.utcnow().strftime('%Y/%m')
+
+ def test_root_index(self):
+ self._post()
+ d = self._blog_date()
+ response = self.app.get('/blog/')
+ assert 'Recent posts' in response
+ assert 'Nothing to see here' in response
+ assert '/blog/%s/my-post/edit' % d in response
+ anon_r = self.app.get('/blog/',
+ extra_environ=dict(username='*anonymous'))
+ # anonymous user can't see Edit links
+ assert 'Nothing to see here' in anon_r
+ assert '/blog/%s/my-post/edit' % d not in anon_r
+
+ def test_root_index_draft(self):
+ self._post(state='draft')
+ d = self._blog_date()
+ response = self.app.get('/blog/')
+ assert 'Recent posts' in response
+ assert 'Nothing to see here' in response
+ assert 'Draft' in response
+ assert '/blog/%s/my-post/edit' % d in response
+ anon_r = self.app.get('/blog/',
+ extra_environ=dict(username='*anonymous'))
+ # anonymous user can't see draft posts
+ assert 'Nothing to see here' not in anon_r
+
+ def test_root_new_post(self):
+ response = self.app.get('/blog/new')
+ assert 'Enter your title here' in response
+
+ def test_validation(self):
+ r = self._post(title='')
+ assert 'You must provide a Title' in r
+
+ def test_root_new_search(self):
+ self._post()
+ response = self.app.get('/blog/search?q=see')
+ assert 'Search' in response
+
+ def test_paging(self):
+ [self._post() for i in range(3)]
+ r = self.app.get('/blog/?limit=1&page=0')
+ assert 'Newer Entries' not in r
+ assert 'Older Entries' in r
+ r = self.app.get('/blog/?limit=1&page=1')
+ assert 'Newer Entries' in r
+ assert 'Older Entries' in r
+ r = self.app.get('/blog/?limit=1&page=2')
+ assert 'Newer Entries' in r
+ assert 'Older Entries' not in r
+
+ def test_discussion_admin(self):
+ r = self.app.get('/blog/')
+ r = self.app.get('/admin/blog/options', validate_chunk=True)
+ assert 'Allow discussion/commenting on posts' in r
+ # Turn discussion on
+ r = self.app.post('/admin/blog/set_options',
+ params=dict(show_discussion='1'))
+ self._post()
+ d = self._blog_date()
+ r = self.app.get('/blog/%s/my-post/' % d)
+ assert '<div class="markdown_edit">' in r
+ # Turn discussion off
+ r = self.app.post('/admin/blog/set_options')
+ r = self.app.get('/blog/%s/my-post/' % d)
+ assert '<div class="markdown_edit">' not in r
+
+ def test_post_index(self):
+ self._post()
+ d = self._blog_date()
+ response = self.app.get('/blog/%s/my-post/' % d)
+ assert 'Nothing to see here' in response
+ assert '/blog/%s/my-post/edit' % d in response
+ anon_r = self.app.get('/blog/%s/my-post/' % d,
+ extra_environ=dict(username='*anonymous'))
+ # anonymous user can't see Edit links
+ assert 'Nothing to see here' in anon_r
+ assert '/blog/%s/my-post/edit' % d not in anon_r
+ self.app.get('/blog/%s/no-my-post' % d, status=404)
+
+ def test_post_index_draft(self):
+ self._post(state='draft')
+ d = self._blog_date()
+ response = self.app.get('/blog/%s/my-post/' % d)
+ assert 'Nothing to see here' in response
+ assert 'Draft' in response
+ assert '/blog/%s/my-post/edit' % d in response
+ anon_r = self.app.get('/blog/%s/my-post/' % d,
+ extra_environ=dict(username='*anonymous'))
+ # anonymous user can't get to draft posts
+ assert 'Nothing to see here' not in anon_r
+
+ def test_post_edit(self):
+ self._post()
+ d = self._blog_date()
+ response = self.app.get('/blog/%s/my-post/edit' % d)
+ assert 'Nothing' in response
+ # anon users can't edit
+ response = self.app.get('/blog/%s/my-post/edit' % d,
+ extra_environ=dict(username='*anonymous'))
+ assert 'Nothing' not in response
+
+ def test_post_history(self):
+ self._post()
+ d = self._blog_date()
+ self._post('/%s/my-post' % d)
+ self._post('/%s/my-post' % d)
+ response = self.app.get('/blog/%s/my-post/history' % d)
+ assert 'My Post' in response
+ # two revisions are shown
+ assert '2 by Test Admin' in response
+ assert '1 by Test Admin' in response
+ self.app.get('/blog/%s/my-post?version=1' % d)
+ self.app.get('/blog/%s/my-post?version=foo' % d, status=404)
+
+ def test_post_diff(self):
+ self._post()
+ d = self._blog_date()
+ self._post('/%s/my-post' % d, text='sometext')
+ self.app.post('/blog/%s/my-post/revert' % d, params=dict(version='1'))
+ response = self.app.get('/blog/%s/my-post/' % d)
+ response = self.app.get('/blog/%s/my-post/diff?v1=0&v2=0' % d)
+ assert 'My Post' in response
+
+ def test_feeds(self):
+ self.app.get('/blog/feed.rss')
+ self.app.get('/blog/feed.atom')
+
+ def test_post_feeds(self):
+ self._post()
+ d = self._blog_date()
+ response = self.app.get('/blog/%s/my-post/feed.rss' % d)
+ assert 'Nothing to see' in response
+ response = self.app.get('/blog/%s/my-post/feed.atom' % d)
+ assert 'Nothing to see' in response
+
+ def test_related_artifacts(self):
+ self._post(title='one')
+ d = self._blog_date()
+ self._post(title='two', text='[blog:%s/one]' % d)
+ M.MonQTask.run_ready()
+ ThreadLocalORMSession.flush_all()
+ r= self.app.get('/blog/%s/one/' % d)
+ assert 'Related' in r
+ assert 'Blog Post: %s/two' % d in r
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/b129d544/AlluraBitergiaMetrics/bitergiametrics/tests/test_roles.py
----------------------------------------------------------------------
diff --git a/AlluraBitergiaMetrics/bitergiametrics/tests/test_roles.py b/AlluraBitergiaMetrics/bitergiametrics/tests/test_roles.py
new file mode 100644
index 0000000..4394f59
--- /dev/null
+++ b/AlluraBitergiaMetrics/bitergiametrics/tests/test_roles.py
@@ -0,0 +1,28 @@
+from pylons import c, g
+
+from alluratest.controller import setup_basic_test, setup_global_objects
+from allura import model as M
+from allura.lib import security
+from allura.lib import helpers as h
+
+def setUp():
+ setup_basic_test()
+ setup_global_objects()
+ h.set_context('test', neighborhood='Projects')
+ c.project.install_app('blog', 'blog')
+ g.set_app('blog')
+
+def test_role_assignments():
+ admin = M.User.by_username('test-admin')
+ user = M.User.by_username('test-user')
+ anon = M.User.anonymous()
+ def check_access(perm):
+ pred = security.has_access(c.app, perm)
+ return pred(user=admin), pred(user=user), pred(user=anon)
+ assert check_access('configure') == (True, False, False)
+ assert check_access('read') == (True, True, True)
+ assert check_access('write') == (True, False, False)
+ assert check_access('unmoderated_post') == (True, True, False)
+ assert check_access('post') == (True, True, False)
+ assert check_access('moderate') == (True, False, False)
+ assert check_access('admin') == (True, False, False)
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/b129d544/AlluraBitergiaMetrics/bitergiametrics/tests/unit/__init__.py
----------------------------------------------------------------------
diff --git a/AlluraBitergiaMetrics/bitergiametrics/tests/unit/__init__.py b/AlluraBitergiaMetrics/bitergiametrics/tests/unit/__init__.py
new file mode 100644
index 0000000..e08129c
--- /dev/null
+++ b/AlluraBitergiaMetrics/bitergiametrics/tests/unit/__init__.py
@@ -0,0 +1,31 @@
+from pylons import c
+from ming.orm.ormsession import ThreadLocalORMSession
+
+from allura.websetup import bootstrap
+from allura.lib import helpers as h
+from allura.lib import plugin
+from allura import model as M
+from alluratest.controller import setup_basic_test
+
+
+def setUp():
+ setup_basic_test()
+
+class BlogTestWithModel(object):
+ def setUp(self):
+ bootstrap.wipe_database()
+ project_reg = plugin.ProjectRegistrationProvider.get()
+ c.user = bootstrap.create_user('Test User')
+ neighborhood = M.Neighborhood(name='Projects', url_prefix='/p/',
+ features=dict(private_projects = False,
+ max_projects = None,
+ css = 'none',
+ google_analytics = False))
+ project_reg.register_neighborhood_project(neighborhood, [c.user])
+ c.project = neighborhood.register_project('test', c.user)
+ c.project.install_app('Blog', 'blog')
+ ThreadLocalORMSession.flush_all()
+ h.set_context('test', 'blog', neighborhood='Projects')
+
+ def tearDown(self):
+ ThreadLocalORMSession.close_all()
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/b129d544/AlluraBitergiaMetrics/bitergiametrics/tests/unit/test_blog_post.py
----------------------------------------------------------------------
diff --git a/AlluraBitergiaMetrics/bitergiametrics/tests/unit/test_blog_post.py b/AlluraBitergiaMetrics/bitergiametrics/tests/unit/test_blog_post.py
new file mode 100644
index 0000000..9dcba4f
--- /dev/null
+++ b/AlluraBitergiaMetrics/bitergiametrics/tests/unit/test_blog_post.py
@@ -0,0 +1,83 @@
+from datetime import datetime
+from nose.tools import assert_equal
+
+from forgeblog import model as M
+from forgeblog.tests.unit import BlogTestWithModel
+
+def wrapped(s):
+ return '<div class="markdown_content"><p>%s</p></div>' % s
+
+class TestHtmlPreview(BlogTestWithModel):
+ def _make_post(self, text):
+ post = M.BlogPost()
+ post.text = text
+ post.make_slug()
+ return post
+
+ def test_single_long_paragraph(self):
+ text = ("Lorem ipsum dolor sit amet, consectetur adipisicing elit, "
+ "sed do eiusmod tempor incididunt ut labore et dolore magna "
+ "aliqua. Ut enim ad minim veniam, quis nostrud exercitation "
+ "ullamco laboris nisi ut aliquip ex ea commodo consequat. "
+ "Duis aute irure dolor in reprehenderit in voluptate velit "
+ "esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
+ "occaecat cupidatat non proident, sunt in culpa qui officia "
+ "deserunt mollit anim id est laborum.")
+ assert_equal(self._make_post(text).html_text_preview, wrapped(text))
+
+ def test_single_short_paragraph(self):
+ text = ("Lorem ipsum dolor sit amet, consectetur adipisicing elit, "
+ "sed do eiusmod tempor incididunt ut labore et dolore magna "
+ "aliqua. Ut enim ad minim veniam, quis nostrud exercitation "
+ "ullamco laboris nisi ut aliquip ex ea commodo consequat.")
+ assert_equal(self._make_post(text).html_text_preview, wrapped(text))
+
+ def test_multi_paragraph_short(self):
+ text = ("Lorem ipsum dolor sit amet, consectetur adipisicing elit, "
+ "sed do eiusmod tempor incididunt ut labore et dolore magna "
+ "aliqua."
+ "\n\n"
+ "Ut enim ad minim veniam, quis nostrud exercitation "
+ "ullamco laboris nisi ut aliquip ex ea commodo consequat.")
+
+ expected = ('<div class="markdown_content"><p>Lorem ipsum dolor sit '
+ 'amet, consectetur adipisicing elit, sed do eiusmod '
+ 'tempor incididunt ut labore et dolore magna aliqua.</p>\n'
+ '<p>Ut enim ad minim veniam, quis nostrud exercitation '
+ 'ullamco laboris nisi ut aliquip ex ea commodo '
+ 'consequat.</p></div>')
+ assert_equal(self._make_post(text).html_text_preview, expected)
+
+ def test_multi_paragraph_long(self):
+ text = ("Lorem ipsum dolor sit amet, consectetur adipisicing elit, "
+ "sed do eiusmod tempor incididunt ut labore et dolore magna "
+ "aliqua."
+ "\n\n"
+ "Lorem ipsum dolor sit amet, consectetur adipisicing elit, "
+ "sed do eiusmod tempor incididunt ut labore et dolore magna "
+ "aliqua. Ut enim ad minim veniam, quis nostrud exercitation "
+ "ullamco laboris nisi ut aliquip ex ea commodo consequat. "
+ "Duis aute irure dolor in reprehenderit in voluptate velit "
+ "esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
+ "occaecat cupidatat non proident, sunt in culpa qui officia "
+ "deserunt mollit anim id est laborum."
+ "\n\n"
+ "Ut enim ad minim veniam, quis nostrud exercitation "
+ "ullamco laboris nisi ut aliquip ex ea commodo consequat.")
+
+ now = datetime.utcnow()
+ expected = ('<div class="markdown_content"><p>Lorem ipsum dolor sit '
+ 'amet, consectetur adipisicing elit, sed do eiusmod '
+ 'tempor incididunt ut labore et dolore magna aliqua.</p>\n'
+ '<p>Lorem ipsum dolor sit amet, consectetur adipisicing '
+ 'elit, sed do eiusmod tempor incididunt ut labore et '
+ 'dolore magna aliqua. Ut enim ad minim veniam, quis '
+ 'nostrud exercitation ullamco laboris nisi ut aliquip ex '
+ 'ea commodo consequat. Duis aute irure dolor in '
+ 'reprehenderit in voluptate velit esse cillum dolore eu '
+ 'fugiat nulla pariatur. Excepteur sint occaecat cupidatat '
+ 'non proident, sunt in culpa qui officia deserunt mollit '
+ 'anim id est laborum.... '
+ '<a href="/p/test/blog/%s/%02i/untitled/">read more</a>'
+ '</p></div>') % (now.year, now.month)
+ assert_equal(self._make_post(text).html_text_preview, expected)
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/b129d544/AlluraBitergiaMetrics/bitergiametrics/version.py
----------------------------------------------------------------------
diff --git a/AlluraBitergiaMetrics/bitergiametrics/version.py b/AlluraBitergiaMetrics/bitergiametrics/version.py
new file mode 100644
index 0000000..6514373
--- /dev/null
+++ b/AlluraBitergiaMetrics/bitergiametrics/version.py
@@ -0,0 +1,2 @@
+__version_info__ = (0, 0)
+__version__ = '.'.join(map(str, __version_info__))
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/b129d544/AlluraBitergiaMetrics/bitergiametrics/widgets.py
----------------------------------------------------------------------
diff --git a/AlluraBitergiaMetrics/bitergiametrics/widgets.py b/AlluraBitergiaMetrics/bitergiametrics/widgets.py
new file mode 100644
index 0000000..7887953
--- /dev/null
+++ b/AlluraBitergiaMetrics/bitergiametrics/widgets.py
@@ -0,0 +1,22 @@
+import ew as ew_core
+import ew.jinja2_ew as ew
+
+from formencode import validators as fev
+
+from allura.lib.widgets import form_fields as ffw
+from allura.lib.widgets import forms
+from allura import model as M
+
+class ViewMetricsForm(ew_core.Widget):
+ template='jinja:forgeblog:templates/metrics_widgets/view_metrics.html'
+ defaults=dict(
+ ew_core.Widget.defaults,
+ value=None,
+ subscribed=None,
+ base_post=None)
+
+ def __call__(self, **kw):
+ kw = super(ViewMetricsForm, self).__call__(**kw)
+ kw['subscribed'] = \
+ M.Mailbox.subscribed(artifact=kw.get('value'))
+ return kw
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/b129d544/AlluraBitergiaMetrics/setup.cfg
----------------------------------------------------------------------
diff --git a/AlluraBitergiaMetrics/setup.cfg b/AlluraBitergiaMetrics/setup.cfg
new file mode 100644
index 0000000..01bb954
--- /dev/null
+++ b/AlluraBitergiaMetrics/setup.cfg
@@ -0,0 +1,3 @@
+[egg_info]
+tag_build = dev
+tag_svn_revision = true
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/b129d544/AlluraBitergiaMetrics/setup.py
----------------------------------------------------------------------
diff --git a/AlluraBitergiaMetrics/setup.py b/AlluraBitergiaMetrics/setup.py
new file mode 100644
index 0000000..58fc8d8
--- /dev/null
+++ b/AlluraBitergiaMetrics/setup.py
@@ -0,0 +1,29 @@
+from setuptools import setup, find_packages
+import sys, os
+
+from bitergiametrics.version import __version__
+
+setup(name='BitergiaMetrics',
+ version=__version__,
+ description="",
+ long_description="""\
+""",
+ classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
+ keywords='',
+ author='Alvaro del Castillo, Bitergia',
+ author_email='acs@bitergia.com',
+ url='',
+ license='Apache License Version 2.0',
+ packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
+ include_package_data=True,
+ zip_safe=False,
+ install_requires=[
+ # -*- Extra requirements: -*-
+ 'allura',
+ ],
+ entry_points="""
+ # -*- Entry points: -*-
+ [allura]
+ metrics=bitergiametrics.main:BitergiaMetricsApp
+ """,
+ )
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/b129d544/AlluraBitergiaMetrics/test.ini
----------------------------------------------------------------------
diff --git a/AlluraBitergiaMetrics/test.ini b/AlluraBitergiaMetrics/test.ini
new file mode 100644
index 0000000..3a32ab4
--- /dev/null
+++ b/AlluraBitergiaMetrics/test.ini
@@ -0,0 +1,54 @@
+#
+# allura - TurboGears 2 testing environment configuration
+#
+# The %(here)s variable will be replaced with the parent directory of this file
+#
+[DEFAULT]
+debug = true
+
+[server:main]
+use = egg:Paste#http
+host = 0.0.0.0
+port = 5000
+
+[app:main]
+use = config:../Allura/test.ini
+
+[app:main_without_authn]
+use = config:../Allura/test.ini#main_without_authn
+
+[app:main_with_amqp]
+use = config:../Allura/test.ini#main_with_amqp
+
+[loggers]
+keys = root, allura, tool
+
+[handlers]
+keys = test
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = INFO
+handlers = test
+
+[logger_allura]
+level = DEBUG
+handlers =
+qualname = allura
+
+[logger_tool]
+level = DEBUG
+handlers =
+qualname = bitergiametrics
+
+[handler_test]
+class = FileHandler
+args = ('test.log',)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(asctime)s,%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
+datefmt = %H:%M:%S