[Checkins] SVN: lovely.tag/trunk/src/lovely/tag/ added normalize
method to engine
Bernd Dorn
bernd.dorn at lovelysystems.com
Mon Jan 8 12:49:30 EST 2007
Log message for revision 71822:
added normalize method to engine
Changed:
U lovely.tag/trunk/src/lovely/tag/README.txt
U lovely.tag/trunk/src/lovely/tag/browser/README.txt
U lovely.tag/trunk/src/lovely/tag/browser/configure.zcml
U lovely.tag/trunk/src/lovely/tag/browser/engine.py
U lovely.tag/trunk/src/lovely/tag/browser/tag.py
U lovely.tag/trunk/src/lovely/tag/configure.zcml
U lovely.tag/trunk/src/lovely/tag/engine.py
U lovely.tag/trunk/src/lovely/tag/ftesting.zcml
U lovely.tag/trunk/src/lovely/tag/interfaces.py
-=-
Modified: lovely.tag/trunk/src/lovely/tag/README.txt
===================================================================
--- lovely.tag/trunk/src/lovely/tag/README.txt 2007-01-08 17:34:19 UTC (rev 71821)
+++ lovely.tag/trunk/src/lovely/tag/README.txt 2007-01-08 17:49:28 UTC (rev 71822)
@@ -619,3 +619,34 @@
0
>>> len(sorted(engine.getItems(tags=[u'renamedtag'])))
2
+
+Normalizing Tags
+----------------
+
+It is also possible to normalize tags with a callable ojbect which
+returns a new name for any given name.
+lower case.
+
+ >>> engine.update(123, 'jukart', [u'RenamedTag', u'USA'])
+ >>> sorted(engine.getTags())
+ [u'RenamedTag', u'USA', u'renamedtag', u'someothertag', u'usa']
+
+Let us normalize all tags to lowercase by using the lower function
+from the string module.
+
+ >>> import string
+
+The normalize method returns the number of tag objects affected.
+
+ >>> engine.normalize(string.lower)
+ 2
+ >>> sorted(engine.getTags())
+ [u'renamedtag', u'someothertag', u'usa']
+
+The normalize method also accepts a python dotted name, which will be
+resolved to a global object.
+
+ >>> engine.normalize('string.upper')
+ 7
+ >>> sorted(engine.getTags())
+ [u'RENAMEDTAG', u'SOMEOTHERTAG', u'USA']
Modified: lovely.tag/trunk/src/lovely/tag/browser/README.txt
===================================================================
--- lovely.tag/trunk/src/lovely/tag/browser/README.txt 2007-01-08 17:34:19 UTC (rev 71821)
+++ lovely.tag/trunk/src/lovely/tag/browser/README.txt 2007-01-08 17:49:28 UTC (rev 71822)
@@ -38,3 +38,52 @@
<span class="tag1">mysteries(1)</span>
</div>
+
+Engine specific Views
+---------------------
+
+CSV export of tag database:
+
+ >>> engine = 'http://localhost/tags/++etc++site/default/tagging-engine/'
+ >>> browser.open(engine + '@@tags.csv')
+ >>> print browser.contents
+ Name,User,Item,Timestamp
+ ...
+
+Normalize Tags:
+
+ >>> browser.open(engine + 'manage.html')
+ >>> browser.getControl(u'Normalize').click()
+ >>> u'No normalizer function defined' in browser.contents
+ True
+
+All tags are lowercase so it should not affect any tags.
+
+ >>> browser.getControl(u'Normalizer').value="string.lower"
+ >>> browser.getControl(u'Normalize').click()
+ >>> print browser.contents
+ <...<div class="summary">Normalized 0 tag objects</div>...
+
+Let us convert it to upper case.
+
+ >>> browser.getControl(u'Normalizer').value="string.upper"
+ >>> browser.getControl(u'Normalize').click()
+ >>> print browser.contents
+ <...<div class="summary">Normalized 111 tag objects</div>...
+
+ >>> browser.open('http://localhost/tags/@@tagCloud')
+ >>> print browser.contents
+ <div class="tagCloud">
+ <span class="tag1">ADAM(1)</span>
+ <span class="tag6">ALEX(2)</span>
+ <span class="tag1">ALTERNATIVE(1)</span>
+ <span class="tag1">AMSTERDAM(1)</span>
+ <span class="tag1">ANIMALS(1)</span>
+ ...
+
+Cleaning of stale items:
+
+ >>> browser.open(engine + 'manage.html')
+ >>> browser.getControl(u'Clean Stale Items').click()
+ >>> print browser.contents
+ <...<div class="summary">Cleaned out 1 items</div>...
Modified: lovely.tag/trunk/src/lovely/tag/browser/configure.zcml
===================================================================
--- lovely.tag/trunk/src/lovely/tag/browser/configure.zcml 2007-01-08 17:34:19 UTC (rev 71821)
+++ lovely.tag/trunk/src/lovely/tag/browser/configure.zcml 2007-01-08 17:49:28 UTC (rev 71822)
@@ -53,5 +53,15 @@
name="manage.html"
/>
+ <browser:page
+ menu="zmi_views"
+ title="Manage"
+ for="lovely.tag.interfaces.ITaggingEngine"
+ permission="lovely.tag.ManageEngine"
+ class=".engine.CSVExportView"
+ name="tags.csv"
+ />
+
+
</configure>
Modified: lovely.tag/trunk/src/lovely/tag/browser/engine.py
===================================================================
--- lovely.tag/trunk/src/lovely/tag/browser/engine.py 2007-01-08 17:34:19 UTC (rev 71821)
+++ lovely.tag/trunk/src/lovely/tag/browser/engine.py 2007-01-08 17:49:28 UTC (rev 71822)
@@ -18,21 +18,57 @@
__docformat__ = "reStructuredText"
from zope.publisher.browser import BrowserView
-from zope import component, schema
+from zope import schema
from zope.cachedescriptors.property import Lazy
from zope.app.pagetemplate import ViewPageTemplateFile
from zope.formlib import form
from lovely.tag import _
-
from zope.formlib import form
+import csv
+import cStringIO
+from zope.cachedescriptors.property import Lazy
class ManageView(form.PageForm):
label=_(u"Manage Tagging Engine")
- form_fields = form.Fields()
+ form_fields = form.Fields(
+ schema.DottedName(__name__=u'normalizer',
+ title=_(u'Normalizer Function'),
+ required=False)
+ )
@form.action(label=_(u'Clean Stale Items'))
def cleanStale(self, action, data):
cleaned = self.context.cleanStaleItems()
self.status = u'Cleaned out %s items' % len(cleaned)
+
+
+ @form.action(label=_(u'Normalize'))
+ def normalize(self, action, data):
+ normalizer = data.get('normalizer')
+ if not normalizer:
+ self.status=_(u'No normalizer function defined')
+ return
+ count = self.context.normalize(normalizer)
+ self.status = u'Normalized %s tag objects' % count
+
+
+class CSVExportView(BrowserView):
+
+ def __call__(self):
+ self.request.response.setHeader('Content-Type', 'text/csv')
+ res = cStringIO.StringIO()
+ writer = csv.writer(res, dialect=csv.excel)
+ encoding = 'utf-8'
+ writer.writerow(('Name', 'User', 'Item', 'Timestamp'))
+ for tag in self.context.getTagObjects():
+ row = [tag.name.encode(encoding)]
+ row.append(tag.user.encode(encoding))
+ row.append(tag.item)
+ row.append(tag.timestamp)
+ writer.writerow(row)
+ return res.getvalue()
+
+
+
Modified: lovely.tag/trunk/src/lovely/tag/browser/tag.py
===================================================================
--- lovely.tag/trunk/src/lovely/tag/browser/tag.py 2007-01-08 17:34:19 UTC (rev 71821)
+++ lovely.tag/trunk/src/lovely/tag/browser/tag.py 2007-01-08 17:49:28 UTC (rev 71822)
@@ -28,7 +28,6 @@
import datetime
from zope.interface.common import idatetime
-
class TaggingMixin(object):
@Lazy
@@ -39,10 +38,10 @@
def tagging(self):
return ITagging(self.context)
- def getCloud(self, maxTags=100):
+ def getCloud(self, maxTags=100, calc=None):
"""returns a tag cloud"""
cloud = self.engine.getCloud()
- return normalize(cloud, maxTags)
+ return normalize(cloud, maxTags, 6, calc)
class TaggingView(BrowserView, TaggingMixin):
@@ -64,17 +63,19 @@
def __init__(self, context, request):
super(RelatedView, self).__init__(context, request)
- def getCloud(self, tag=None, maxTags=100):
+ def getCloud(self, tag=None, maxTags=100, calc=None):
"""returns a tag cloud"""
if tag is None:
tag = self.request.get('tagname',None)
if tag is None:
return []
cloud = self.engine.getFrequency(self.engine.getRelatedTags(tag))
- return normalize(cloud, maxTags)
+ return normalize(cloud, maxTags, 6, calc)
-def normalize(cloud, maxTags=100, maxValue=6):
+def normalize(cloud, maxTags=100, maxValue=6, calc=None):
+ if calc is None:
+ calc = lambda x: x
if len(cloud) == 0:
return []
minmax = sorted(cloud, key=lambda i: i[1],reverse=True)
@@ -86,8 +87,8 @@
if end == 0:
return []
minmax = minmax[:end]
- minFreq = minmax[-1][1]
- maxFreq = minmax[0][1]
+ minFreq = calc(minmax[-1][1])
+ maxFreq = calc(minmax[0][1])
freqRange = maxFreq-minFreq
if freqRange>0:
ratio = float(maxValue-1)/freqRange
@@ -98,7 +99,7 @@
if ratio is None:
normalized=1
else:
- normalized = int((frequency-minFreq)*ratio) +1
+ normalized = int((calc(frequency)-minFreq)*ratio) +1
res.append(dict(name=tag,
normalized=normalized,
frequency=frequency,))
@@ -124,7 +125,6 @@
def handle_edit_action(self, action, data):
tags = data.get('tags','')
tags = set(tags.split())
-
user = self.request.principal.id
oldTags = self.tagging.getTags(user)
if oldTags != tags:
Modified: lovely.tag/trunk/src/lovely/tag/configure.zcml
===================================================================
--- lovely.tag/trunk/src/lovely/tag/configure.zcml 2007-01-08 17:34:19 UTC (rev 71821)
+++ lovely.tag/trunk/src/lovely/tag/configure.zcml 2007-01-08 17:49:28 UTC (rev 71822)
@@ -34,7 +34,7 @@
/>
<require
permission="lovely.tag.ManageEngine"
- attributes="cleanStaleItems delete rename"
+ attributes="cleanStaleItems delete rename getTagObjects normalize"
/>
<require
permission="lovely.tag.AccessTag"
@@ -74,7 +74,20 @@
interface=".interfaces.IUserTagging"
/>
</class>
+
+ <class class=".tag.Tag">
+ <require
+ permission="lovely.tag.UpdateTag"
+ set_schema=".interfaces.ITag"
+ />
+ <require
+ permission="lovely.tag.AccessTag"
+ interface=".interfaces.ITag"
+ />
+ </class>
+
+
<adapter
factory=".tagging.UserTagging"
trusted="True"
Modified: lovely.tag/trunk/src/lovely/tag/engine.py
===================================================================
--- lovely.tag/trunk/src/lovely/tag/engine.py 2007-01-08 17:34:19 UTC (rev 71821)
+++ lovely.tag/trunk/src/lovely/tag/engine.py 2007-01-08 17:49:28 UTC (rev 71822)
@@ -26,6 +26,8 @@
from zope.app import intid
from zope.app.intid.interfaces import IIntIdRemovedEvent, IIntIds
from lovely.tag import interfaces, tag
+from zope.dottedname.resolve import resolve
+import types
class TaggingEngine(persistent.Persistent, contained.Contained):
zope.interface.implements(interfaces.ITaggingEngine,
@@ -146,10 +148,10 @@
# shortcut
return set(self._name_to_tagids.keys())
- result = self._getTagObjects(items, users)
+ result = self.getTagObjects(items, users)
return set([tag.name for tag in result])
- def _getTagObjects(self, items, users):
+ def getTagObjects(self, items=None, users=None):
if items is None and users is None:
users_result = set()
@@ -251,13 +253,12 @@
def getCloud(self, items=None, users=None):
"""See interfaces.ITaggingEngine"""
- import types
if type(items) == types.IntType:
items = [items]
if type(users) in types.StringTypes:
users = [users]
- tags = self._getTagObjects(items=items, users=users)
+ tags = self.getTagObjects(items=items, users=users)
d = {}
for tag in tags:
if d.has_key(tag.name):
@@ -305,8 +306,18 @@
self._name_to_tagids[new] = newTagIds
del self._name_to_tagids[old]
return len(tagIds)
-
+ def normalize(self, normalizer):
+ if type(normalizer) == types.StringType:
+ normalizer = resolve(normalizer)
+ names = list(self._name_to_tagids.keys())
+ count = 0
+ for name in names:
+ newName = normalizer(name)
+ if newName != name:
+ count += self.rename(name, newName)
+ return count
+
@component.adapter(IIntIdRemovedEvent)
def removeItemSubscriber(event):
Modified: lovely.tag/trunk/src/lovely/tag/ftesting.zcml
===================================================================
--- lovely.tag/trunk/src/lovely/tag/ftesting.zcml 2007-01-08 17:34:19 UTC (rev 71821)
+++ lovely.tag/trunk/src/lovely/tag/ftesting.zcml 2007-01-08 17:49:28 UTC (rev 71822)
@@ -7,7 +7,8 @@
<meta:provides feature="devmode" />
<include package="zope.app" />
-
+ <include package="zope.app" file="ftesting.zcml"/>
+
<include package="zope.viewlet" file="meta.zcml"/>
<include package="zope.app.securitypolicy" file="meta.zcml" />
@@ -15,8 +16,9 @@
<include package="zope.app.server" />
<include package="zope.app.authentication" />
+
<securityPolicy
- component="zope.app.securitypolicy.zopepolicy.ZopeSecurityPolicy" />
+ component="zope.app.securitypolicy.zopepolicy.ZopeSecurityPolicy" />
<include package="zope.app.securitypolicy" />
@@ -24,7 +26,7 @@
description="All users have this role implicitly" />
<role id="zope.Manager" title="Site Manager" />
- <grantAll role="zope.Manager" />
+
<principal
id="zope.manager"
@@ -75,4 +77,5 @@
<grant permission="zope.app.dublincore.view"
role="zope.Anonymous" />
+ <grantAll role="zope.Manager" />
</configure>
Modified: lovely.tag/trunk/src/lovely/tag/interfaces.py
===================================================================
--- lovely.tag/trunk/src/lovely/tag/interfaces.py 2007-01-08 17:34:19 UTC (rev 71821)
+++ lovely.tag/trunk/src/lovely/tag/interfaces.py 2007-01-08 17:49:28 UTC (rev 71822)
@@ -69,6 +69,11 @@
The method returns a set of *normalized* tag names.
"""
+ def getTagObjects(self, items, users):
+ """same as getTags but returns tag objects implementing
+ ITag"""
+
+
def getCloud(items=None, users=None):
"""Get a set of tuples in the form of ('tag',
frequency). Arguments are the same as getTags."""
@@ -115,6 +120,13 @@
def rename(old, new):
"""rename tags from @old to @new, this method joins the tags
if tags with the new name do exist"""
+
+ def normalize(normalizer):
+ """Normalize tagnames with the given normalizer
+ function. @normalizer can also be a dotted name.
+
+ The function provided should return a new name for an existing
+ name."""
class ITaggingStatistics(zope.interface.Interface):
More information about the Checkins
mailing list