changeset 2674:a221706dab50 beta

merged + fixed pull request #62: Implemented metatags and visualisation options. - new tag lang - fixed found issues - added simple test
author Marcin Kuzminski <marcin@python-works.com>
date Fri, 27 Jul 2012 01:21:07 +0200
parents d5e42c00f3c1
children 31265f80cf8b
files rhodecode/controllers/admin/repos.py rhodecode/controllers/admin/settings.py rhodecode/controllers/admin/users.py rhodecode/lib/base.py rhodecode/lib/helpers.py rhodecode/lib/utils2.py rhodecode/model/db.py rhodecode/model/forms.py rhodecode/public/css/style.css rhodecode/templates/admin/settings/settings.html rhodecode/templates/data_table/_dt_elements.html rhodecode/templates/index_base.html rhodecode/templates/journal/journal.html rhodecode/templates/repo_switcher_list.html rhodecode/templates/summary/summary.html rhodecode/tests/test_libs.py
diffstat 16 files changed, 288 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- a/rhodecode/controllers/admin/repos.py	Fri Jul 27 01:06:50 2012 +0200
+++ b/rhodecode/controllers/admin/repos.py	Fri Jul 27 01:21:07 2012 +0200
@@ -144,20 +144,21 @@
         template = _tmpl_lookup.get_template('data_table/_dt_elements.html')
 
         quick_menu = lambda repo_name: (template.get_def("quick_menu")
-                                        .render(repo_name, _=_, h=h))
+                                        .render(repo_name, _=_, h=h, c=c))
         repo_lnk = lambda name, rtype, private, fork_of: (
             template.get_def("repo_name")
-            .render(name, rtype, private, fork_of, short_name=False, 
-                    admin=True, _=_, h=h))
+            .render(name, rtype, private, fork_of, short_name=False,
+                    admin=True, _=_, h=h, c=c))
 
         repo_actions = lambda repo_name: (template.get_def("repo_actions")
-                                       .render(repo_name, _=_, h=h))
+                                       .render(repo_name, _=_, h=h, c=c))
 
         for repo in c.repos_list:
             repos_data.append({
                 "menu": quick_menu(repo.repo_name),
                 "raw_name": repo.repo_name,
-                "name": repo_lnk(repo.repo_name, repo.repo_type, repo.private, repo.fork),
+                "name": repo_lnk(repo.repo_name, repo.repo_type,
+                                 repo.private, repo.fork),
                 "desc": repo.description,
                 "owner": repo.user.username,
                 "action": repo_actions(repo.repo_name),
--- a/rhodecode/controllers/admin/settings.py	Fri Jul 27 01:06:50 2012 +0200
+++ b/rhodecode/controllers/admin/settings.py	Fri Jul 27 01:21:07 2012 +0200
@@ -45,7 +45,7 @@
 from rhodecode.model.db import RhodeCodeUi, Repository, RepoGroup, \
     RhodeCodeSetting, PullRequest, PullRequestReviewers
 from rhodecode.model.forms import UserForm, ApplicationSettingsForm, \
-    ApplicationUiSettingsForm
+    ApplicationUiSettingsForm, ApplicationVisualisationForm
 from rhodecode.model.scm import ScmModel
 from rhodecode.model.user import UserModel
 from rhodecode.model.db import User
@@ -143,15 +143,15 @@
                 )
 
             try:
-                sett1 = RhodeCodeSetting.get_by_name('title')
+                sett1 = RhodeCodeSetting.get_by_name_or_create('title')
                 sett1.app_settings_value = form_result['rhodecode_title']
                 Session().add(sett1)
 
-                sett2 = RhodeCodeSetting.get_by_name('realm')
+                sett2 = RhodeCodeSetting.get_by_name_or_create('realm')
                 sett2.app_settings_value = form_result['rhodecode_realm']
                 Session().add(sett2)
 
-                sett3 = RhodeCodeSetting.get_by_name('ga_code')
+                sett3 = RhodeCodeSetting.get_by_name_or_create('ga_code')
                 sett3.app_settings_value = form_result['rhodecode_ga_code']
                 Session().add(sett3)
 
@@ -165,6 +165,47 @@
                           'application settings'),
                           category='error')
 
+        if setting_id == 'visual':
+
+            application_form = ApplicationVisualisationForm()()
+            try:
+                form_result = application_form.to_python(dict(request.POST))
+            except formencode.Invalid, errors:
+                return htmlfill.render(
+                     render('admin/settings/settings.html'),
+                     defaults=errors.value,
+                     errors=errors.error_dict or {},
+                     prefix_error=False,
+                     encoding="UTF-8"
+                )
+
+            try:
+                sett1 = RhodeCodeSetting.get_by_name_or_create('show_public_icon')
+                sett1.app_settings_value = \
+                    form_result['rhodecode_show_public_icon']
+
+                sett2 = RhodeCodeSetting.get_by_name_or_create('show_private_icon')
+                sett2.app_settings_value = \
+                    form_result['rhodecode_show_private_icon']
+
+                sett3 = RhodeCodeSetting.get_by_name_or_create('stylify_metatags')
+                sett3.app_settings_value = \
+                    form_result['rhodecode_stylify_metatags']
+
+                Session().add(sett1)
+                Session().add(sett2)
+                Session().add(sett3)
+                Session().commit()
+                set_rhodecode_config(config)
+                h.flash(_('Updated visualisation settings'),
+                        category='success')
+
+            except Exception:
+                log.error(traceback.format_exc())
+                h.flash(_('error occurred during updating '
+                          'visualisation settings'),
+                        category='error')
+
         if setting_id == 'vcs':
             application_form = ApplicationUiSettingsForm()()
             try:
--- a/rhodecode/controllers/admin/users.py	Fri Jul 27 01:06:50 2012 +0200
+++ b/rhodecode/controllers/admin/users.py	Fri Jul 27 01:21:07 2012 +0200
@@ -78,15 +78,15 @@
 
         grav_tmpl = lambda user_email, size: (
                 template.get_def("user_gravatar")
-                .render(user_email, size, _=_, h=h))
+                .render(user_email, size, _=_, h=h, c=c))
 
         user_lnk = lambda user_id, username: (
                 template.get_def("user_name")
-                .render(user_id, username, _=_, h=h))
+                .render(user_id, username, _=_, h=h, c=c))
 
         user_actions = lambda user_id, username: (
                 template.get_def("user_actions")
-                .render(user_id, username, _=_, h=h))
+                .render(user_id, username, _=_, h=h, c=c))
 
         for user in c.users_list:
             users_data.append({
--- a/rhodecode/lib/base.py	Fri Jul 27 01:06:50 2012 +0200
+++ b/rhodecode/lib/base.py	Fri Jul 27 01:21:07 2012 +0200
@@ -17,7 +17,7 @@
 
 from rhodecode import __version__, BACKENDS
 
-from rhodecode.lib.utils2 import str2bool, safe_unicode
+from rhodecode.lib.utils2 import str2bool, safe_unicode, AttributeDict
 from rhodecode.lib.auth import AuthUser, get_container_username, authfunc,\
     HasPermissionAnyMiddleware, CookieStoreWrapper
 from rhodecode.lib.utils import get_repo_slug, invalidate_cache
@@ -158,7 +158,7 @@
             log.debug('proto is %s and SSL is required BAD REQUEST !'
                       % org_proto)
             return False
-        return True 
+        return True
 
     def __call__(self, environ, start_response):
         start = time.time()
@@ -178,6 +178,12 @@
         c.rhodecode_name = config.get('rhodecode_title')
         c.use_gravatar = str2bool(config.get('use_gravatar'))
         c.ga_code = config.get('rhodecode_ga_code')
+        # Visual options
+        c.visual = AttributeDict({})
+        c.visual.show_public_icon = str2bool(config.get('rhodecode_show_public_icon'))
+        c.visual.show_private_icon = str2bool(config.get('rhodecode_show_private_icon'))
+        c.visual.stylify_metatags = str2bool(config.get('rhodecode_stylify_metatags'))
+
         c.repo_name = get_repo_slug(request)
         c.backends = BACKENDS.keys()
         c.unread_notifications = NotificationModel()\
--- a/rhodecode/lib/helpers.py	Fri Jul 27 01:06:50 2012 +0200
+++ b/rhodecode/lib/helpers.py	Fri Jul 27 01:21:07 2012 +0200
@@ -9,6 +9,7 @@
 import urllib
 import math
 import logging
+import re
 
 from datetime import datetime
 from pygments.formatters.html import HtmlFormatter
@@ -430,6 +431,26 @@
     return _author
 
 
+def desc_stylize(value):
+    """
+    converts tags from value into html equivalent
+
+    :param value:
+    """
+    value = re.sub(r'\[see\ \=\>\ *([a-zA-Z0-9\/\=\?\&\ \:\/\.\-]*)\]',
+                   '<div class="metatag" tag="see">see =&gt; \\1 </div>', value)
+    value = re.sub(r'\[license\ \=\>\ *([a-zA-Z0-9\/\=\?\&\ \:\/\.\-]*)\]',
+                   '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/\\1">\\1</a></div>', value)
+    value = re.sub(r'\[(requires|recommends|conflicts|base)\ \=\>\ *([a-zA-Z\-\/]*)\]',
+                   '<div class="metatag" tag="\\1">\\1 =&gt; <a href="/\\2">\\2</a></div>', value)
+    value = re.sub(r'\[(lang|language)\ \=\>\ *([a-zA-Z\-\/]*)\]',
+                   '<div class="metatag" tag="lang">\\2</div>', value)
+    value = re.sub(r'\[([a-z]+)\]',
+                  '<div class="metatag" tag="\\1">\\1</div>', value)
+
+    return value
+
+
 def bool2icon(value):
     """Returns True/False values represented as small html image of true/false
     icons
--- a/rhodecode/lib/utils2.py	Fri Jul 27 01:06:50 2012 +0200
+++ b/rhodecode/lib/utils2.py	Fri Jul 27 01:21:07 2012 +0200
@@ -443,3 +443,9 @@
         usrs.add(username)
 
     return sorted(list(usrs), key=lambda k: k.lower())
+
+class AttributeDict(dict):
+    def __getattr__(self, attr):
+        return self.get(attr, None)
+    __setattr__ = dict.__setitem__
+    __delattr__ = dict.__delitem__
--- a/rhodecode/model/db.py	Fri Jul 27 01:06:50 2012 +0200
+++ b/rhodecode/model/db.py	Fri Jul 27 01:21:07 2012 +0200
@@ -182,9 +182,16 @@
         )
 
     @classmethod
-    def get_by_name(cls, ldap_key):
+    def get_by_name(cls, key):
         return cls.query()\
-            .filter(cls.app_settings_name == ldap_key).scalar()
+            .filter(cls.app_settings_name == key).scalar()
+
+    @classmethod
+    def get_by_name_or_create(cls, key):
+        res = cls.get_by_name(key)
+        if not res:
+            res = cls(key)
+        return res
 
     @classmethod
     def get_app_settings(cls, cache=False):
@@ -589,8 +596,8 @@
     users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
     stats = relationship('Statistics', cascade='all', uselist=False)
 
-    followers = relationship('UserFollowing', 
-                             primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', 
+    followers = relationship('UserFollowing',
+                             primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
                              cascade='all')
 
     logs = relationship('UserLog')
@@ -1547,7 +1554,7 @@
         self._revisions = ':'.join(val)
 
     author = relationship('User', lazy='joined')
-    reviewers = relationship('PullRequestReviewers', 
+    reviewers = relationship('PullRequestReviewers',
                              cascade="all, delete, delete-orphan")
     org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
     other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
--- a/rhodecode/model/forms.py	Fri Jul 27 01:06:50 2012 +0200
+++ b/rhodecode/model/forms.py	Fri Jul 27 01:21:07 2012 +0200
@@ -242,23 +242,30 @@
     return _ApplicationSettingsForm
 
 
+def ApplicationVisualisationForm():
+    class _ApplicationVisualisationForm(formencode.Schema):
+        allow_extra_fields = True
+        filter_extra_fields = False
+        rhodecode_show_public_icon = v.StringBoolean(if_missing=False)
+        rhodecode_show_private_icon = v.StringBoolean(if_missing=False)
+        rhodecode_stylify_metatags = v.StringBoolean(if_missing=False)
+
+    return _ApplicationVisualisationForm
+
+
 def ApplicationUiSettingsForm():
     class _ApplicationUiSettingsForm(formencode.Schema):
         allow_extra_fields = True
         filter_extra_fields = False
-        web_push_ssl = v.OneOf(['true', 'false'], if_missing='false')
+        web_push_ssl = v.StringBoolean(if_missing=False)
         paths_root_path = All(
             v.ValidPath(),
             v.UnicodeString(strip=True, min=1, not_empty=True)
         )
-        hooks_changegroup_update = v.OneOf(['True', 'False'],
-                                           if_missing=False)
-        hooks_changegroup_repo_size = v.OneOf(['True', 'False'],
-                                              if_missing=False)
-        hooks_changegroup_push_logger = v.OneOf(['True', 'False'],
-                                                if_missing=False)
-        hooks_preoutgoing_pull_logger = v.OneOf(['True', 'False'],
-                                                if_missing=False)
+        hooks_changegroup_update = v.StringBoolean(if_missing=False)
+        hooks_changegroup_repo_size = v.StringBoolean(if_missing=False)
+        hooks_changegroup_push_logger = v.StringBoolean(if_missing=False)
+        hooks_preoutgoing_pull_logger = v.StringBoolean(if_missing=False)
 
     return _ApplicationUiSettingsForm
 
@@ -268,7 +275,7 @@
         allow_extra_fields = True
         filter_extra_fields = True
         overwrite_default = v.StringBoolean(if_missing=False)
-        anonymous = v.OneOf(['True', 'False'], if_missing=False)
+        anonymous = v.StringBoolean(if_missing=False)
         default_perm = v.OneOf(perms_choices)
         default_register = v.OneOf(register_choices)
         default_create = v.OneOf(create_choices)
--- a/rhodecode/public/css/style.css	Fri Jul 27 01:06:50 2012 +0200
+++ b/rhodecode/public/css/style.css	Fri Jul 27 01:21:07 2012 +0200
@@ -1827,6 +1827,81 @@
 	
 }
 
+#summary .metatag {
+    display: inline-block;
+    padding: 3px 5px;
+    margin-bottom: 3px;
+    margin-right: 1px;
+    border-radius: 5px;
+}
+
+#content div.box #summary p {
+    margin-bottom: -5px;
+        width: 600px;
+        white-space: pre-wrap;
+}
+
+#content div.box #summary p:last-child {
+    margin-bottom: 9px;
+}
+
+#content div.box #summary p:first-of-type {
+    margin-top: 9px;
+}
+
+ .metatag {
+    display: inline-block;
+    margin-right: 1px;
+    -webkit-border-radius: 4px 4px 4px 4px;
+    -khtml-border-radius: 4px 4px 4px 4px;
+    -moz-border-radius: 4px 4px 4px 4px;
+    border-radius: 4px 4px 4px 4px;
+    
+    border: solid 1px #9CF;
+    padding: 2px 3px 2px 3px !important;
+    background-color: #DEF;    
+}
+
+.metatag[tag="dead"] {
+	background-color: #E44;
+}
+
+.metatag[tag="stale"] {
+    background-color: #EA4;
+}
+
+.metatag[tag="featured"] {
+	background-color: #AEA;
+}
+
+.metatag[tag="requires"] { 
+	background-color: #9CF;
+}
+
+.metatag[tag="recommends"] { 
+	background-color: #BDF; 
+}
+
+.metatag[tag="lang"] { 
+    background-color: #FAF474; 
+}
+
+.metatag[tag="license"] {
+    border: solid 1px #9CF;
+    background-color: #DEF;
+    target-new: tab !important;
+}
+.metatag[tag="see"] {
+    border: solid 1px #CBD;
+    background-color: #EDF;
+}
+
+a.metatag[tag="license"]:hover {
+    background-color: #003367;
+    color: #FFF;
+    text-decoration: none;
+}
+
 #summary .desc {
 	white-space: pre;
 	width: 100%;
--- a/rhodecode/templates/admin/settings/settings.html	Fri Jul 27 01:06:50 2012 +0200
+++ b/rhodecode/templates/admin/settings/settings.html	Fri Jul 27 01:21:07 2012 +0200
@@ -116,6 +116,63 @@
     </div>
     ${h.end_form()}
 
+    <h3>${_('Visualisation settings')}</h3>
+    ${h.form(url('admin_setting', setting_id='visual'),method='put')}
+    <div class="form">
+        <!-- fields -->
+
+        <div class="fields">
+
+             <div class="field">
+                <div class="label label-checkbox">
+                    <label>${_('Icons')}:</label>
+                </div>
+                <div class="checkboxes">
+                    <div class="checkbox">
+                        ${h.checkbox('rhodecode_show_public_icon','True')}
+                        <label for="rhodecode_show_public_icon">${_('Show public repo icon on repositories')}</label>
+                    </div>
+                    <div class="checkbox">
+                        ${h.checkbox('rhodecode_show_private_icon','True')}
+                        <label for="rhodecode_show_private_icon">${_('Show private repo icon on repositories')}</label>
+                    </div>
+                 </div>
+             </div>
+
+             <div class="field">
+                <div class="label label-checkbox">
+                    <label>${_('Meta-Tagging')}:</label>
+                </div>
+                <div class="checkboxes">
+                    <div class="checkbox">
+                        ${h.checkbox('rhodecode_stylify_metatags','True')}
+                        <label for="rhodecode_stylify_metatags">${_('Stylify recognised metatags:')}</label>
+                    </div>
+                    <div style="padding-left: 20px;">
+                        <ul> <!-- Fix style here -->
+                            <li>[featured] <span class="metatag" tag="featured">featured</span></li>
+                            <li>[stale] <span class="metatag" tag="stale">stale</span></li>
+                            <li>[dead] <span class="metatag" tag="dead">dead</span></li>
+                            <li>[lang =&gt; lang] <span class="metatag" tag="lang" >lang</span></li>
+                            <li>[license =&gt; License] <span class="metatag" tag="license"><a href="http://www.opensource.org/licenses/License" >License</a></span></li>                            
+                            <li>[requires =&gt; Repo] <span class="metatag" tag="requires" >requires =&gt; <a href="#" >Repo</a></span></li>
+                            <li>[recommends =&gt; Repo] <span class="metatag" tag="recommends" >recommends =&gt; <a href="#" >Repo</a></span></li>
+                            <li>[see =&gt; URI] <span class="metatag" tag="see">see =&gt; <a href="#">URI</a> </span></li>
+                        </ul>
+                    </div>
+                 </div>
+             </div>
+
+             <div class="buttons">
+                 ${h.submit('save',_('Save settings'),class_="ui-btn large")}
+                 ${h.reset('reset',_('Reset'),class_="ui-btn large")}
+             </div>
+
+        </div>
+    </div>
+    ${h.end_form()}
+
+
     <h3>${_('VCS settings')}</h3>
     ${h.form(url('admin_setting', setting_id='vcs'),method='put')}
     <div class="form">
--- a/rhodecode/templates/data_table/_dt_elements.html	Fri Jul 27 01:06:50 2012 +0200
+++ b/rhodecode/templates/data_table/_dt_elements.html	Fri Jul 27 01:21:07 2012 +0200
@@ -63,10 +63,10 @@
    %endif
 
    ##PRIVATE/PUBLIC
-   %if private:
-      <img class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="${h.url('/images/icons/lock.png')}"/>
-   %else:
-      <img class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="${h.url('/images/icons/lock_open.png')}"/>
+   %if private and c.visual.show_private_icon:
+     <img class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="${h.url('/images/icons/lock.png')}"/>
+   %elif not private and c.visual.show_public_icon:
+     <img class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="${h.url('/images/icons/lock_open.png')}"/>
    %endif
 
    ##NAME
@@ -108,4 +108,3 @@
 <%def name="user_name(user_id, username)">
     ${h.link_to(username,h.url('edit_user', id=user_id))}
 </%def>
-
--- a/rhodecode/templates/index_base.html	Fri Jul 27 01:06:50 2012 +0200
+++ b/rhodecode/templates/index_base.html	Fri Jul 27 01:21:07 2012 +0200
@@ -41,7 +41,11 @@
                             ${h.link_to(gr.name,url('repos_group_home',group_name=gr.group_name))}
                             </div>
                         </td>
-                        <td>${gr.group_description}</td>
+                        %if c.visual.stylify_metatags:
+                            <td>${h.desc_stylize(gr.group_description)}</td>
+                        %else:
+                            <td>${gr.group_description}</td>
+                        %endif
                         ## this is commented out since for multi nested repos can be HEAVY!
                         ## in number of executed queries during traversing uncomment at will
                         ##<td><b>${gr.repositories_recursive_count}</b></td>
@@ -85,7 +89,11 @@
                     </td>
                     ##DESCRIPTION
                     <td><span class="tooltip" title="${h.tooltip(repo['description'])}">
+                       %if c.visual.stylify_metatags:
+                       ${h.urlify_text(h.desc_stylize(h.truncate(repo['description'],60)))}</span>
+                       %else:
                        ${h.truncate(repo['description'],60)}</span>
+                       %endif
                     </td>
                     ##LAST CHANGE DATE
                     <td>
--- a/rhodecode/templates/journal/journal.html	Fri Jul 27 01:06:50 2012 +0200
+++ b/rhodecode/templates/journal/journal.html	Fri Jul 27 01:21:07 2012 +0200
@@ -128,9 +128,9 @@
                            <img class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="${h.url('/images/icons/giticon.png')}"/>
                          %endif
 
-                        %if entry.follows_repository.private:
+                        %if entry.follows_repository.private and c.visual.show_private_icon:
                           <img class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="${h.url('/images/icons/lock.png')}"/>
-                        %else:
+                        %elif not entry.follows_repository.private and c.visual.show_public_icon:
                           <img class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="${h.url('/images/icons/lock_open.png')}"/>
                         %endif
                         <span class="watched_repo">
--- a/rhodecode/templates/repo_switcher_list.html	Fri Jul 27 01:06:50 2012 +0200
+++ b/rhodecode/templates/repo_switcher_list.html	Fri Jul 27 01:21:07 2012 +0200
@@ -6,12 +6,12 @@
 
 %for repo in c.repos_list:
 
-      %if repo['dbrepo']['private']:
+      %if repo['dbrepo']['private'] and c.visual.show_private_icon:
          <li>
              <img src="${h.url('/images/icons/lock.png')}" alt="${_('Private repository')}" class="repo_switcher_type"/>
              ${h.link_to(repo['name'],h.url('summary_home',repo_name=repo['name']),class_="repo_name %s" % repo['dbrepo']['repo_type'])}
           </li>
-      %else:
+      %elif not repo['dbrepo']['private'] and c.visual.show_public_icon:
          <li>
              <img src="${h.url('/images/icons/lock_open.png')}" alt="${_('Public repository')}" class="repo_switcher_type" />
              ${h.link_to(repo['name'],h.url('summary_home',repo_name=repo['name']),class_="repo_name %s" % repo['dbrepo']['repo_type'])}
--- a/rhodecode/templates/summary/summary.html	Fri Jul 27 01:06:50 2012 +0200
+++ b/rhodecode/templates/summary/summary.html	Fri Jul 27 01:21:07 2012 +0200
@@ -104,7 +104,11 @@
 			  <div class="label-summary">
 			      <label>${_('Description')}:</label>
 			  </div>
-			  <div class="input ${summary(c.show_stats)} desc">${h.urlify_text(c.dbrepo.description)}</div>
+              %if c.visual.stylify_metatags:
+                <div class="input ${summary(c.show_stats)} desc">${h.urlify_text(h.desc_stylize(c.dbrepo.description))}</div>
+              %else:
+                <div class="input ${summary(c.show_stats)} desc">${h.urlify_text(c.dbrepo.description)}</div>
+              %endif        
 			 </div>
 
 			 <div class="field">
--- a/rhodecode/tests/test_libs.py	Fri Jul 27 01:06:50 2012 +0200
+++ b/rhodecode/tests/test_libs.py	Fri Jul 27 01:21:07 2012 +0200
@@ -131,3 +131,19 @@
         self.assertEqual(age(n - delt(hours=24 * (calendar.mdays[n.month-1] + 2))),
                          u'1 month and 2 days ago')
         self.assertEqual(age(n - delt(hours=24 * 400)), u'1 year and 1 month ago')
+
+    def test_tag_exctrator(self):
+        sample = (
+            "hello pta[tag] gog [[]] [[] sda ero[or]d [me =>>< sa]"
+            "[requires] [stale] [see<>=>] [see => http://url.com]"
+            "[requires => url] [lang => python] [just a tag]"
+            "[,d] [ => ULR ] [obsolete] [desc]]"
+        )
+        from rhodecode.lib.helpers import desc_stylize
+        res = desc_stylize(sample)
+        self.assertTrue('<div class="metatag" tag="tag">tag</div>' in res)
+        self.assertTrue('<div class="metatag" tag="obsolete">obsolete</div>' in res)
+        self.assertTrue('<div class="metatag" tag="stale">stale</div>' in res)
+        self.assertTrue('<div class="metatag" tag="lang">python</div>' in res)
+        self.assertTrue('<div class="metatag" tag="requires">requires =&gt; <a href="/url">url</a></div>' in res)
+        self.assertTrue('<div class="metatag" tag="tag">tag</div>' in res)