[Checkins] SVN: Sandbox/luciano/kirbi/src/kirbi/ moved the
NameChooser to app, renaming it to QuickNameChooser
Luciano Ramalho
luciano at ramalho.org
Sat Aug 18 18:30:12 EDT 2007
Log message for revision 78972:
moved the NameChooser to app, renaming it to QuickNameChooser
start implementing collections
Changed:
U Sandbox/luciano/kirbi/src/kirbi/app.py
U Sandbox/luciano/kirbi/src/kirbi/copy.py
U Sandbox/luciano/kirbi/src/kirbi/interfaces.py
U Sandbox/luciano/kirbi/src/kirbi/pac.py
-=-
Modified: Sandbox/luciano/kirbi/src/kirbi/app.py
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/app.py 2007-08-18 20:43:31 UTC (rev 78971)
+++ Sandbox/luciano/kirbi/src/kirbi/app.py 2007-08-18 22:30:11 UTC (rev 78972)
@@ -18,6 +18,7 @@
from grok import index
from kirbi.pac import Pac
from kirbi.book import Book
+from kirbi.collection import Collection
from kirbi.interfaces import IUser
from zope.interface import Interface, implements
from zope.component import getSiteManager
@@ -36,7 +37,11 @@
from zope import schema
from zope.component import getUtility
+from zope.app.container.contained import NameChooser
+from zope.app.container.interfaces import INameChooser
+
PAC_NAME = u'pac'
+COLLECTIONS_FOLDER_NAME = u'u'
grok.define_permission('kirbi.AddCopy')
grok.define_permission('kirbi.ManageBook')
@@ -64,6 +69,7 @@
def __init__(self):
super(Kirbi, self).__init__()
self.pac = self[PAC_NAME] = Pac()
+ self.collections = self[COLLECTIONS_FOLDER_NAME] = CollectionsFolder()
@grok.subscribe(Kirbi, grok.IObjectAddedEvent)
def grant_permissions(app, event):
@@ -72,6 +78,7 @@
role_manager.grantPermissionToRole('kirbi.ManageBook', 'kirbi.Owner')
class Index(grok.View):
+ grok.context(Kirbi)
def pac_url(self):
return self.url(self.context.pac)
@@ -87,7 +94,7 @@
isbn13 = index.Field()
searchableText = index.Text()
- creatorsSet = index.Set()
+ creatorsSet = grok.index.Set()
class Master(grok.View):
"""The master page template macro."""
@@ -128,7 +135,8 @@
#XXX: change this method to use our UserFolder and User class instead
# of PrincipalFolder and InternalPrincipal
login = data['login']
- #self.context[login] = User(**data)
+ title = data.get('name') or login # name is blank or None, use login
+ self.context.collections[login] = Collection(title)
# add principal to principal folder
pau = getUtility(IAuthentication)
@@ -141,4 +149,45 @@
role_manager.assignRoleToPrincipal('kirbi.Owner',
principals.prefix + login)
self.redirect(self.url('login')+'?'+urlencode({'login':login}))
+
+class CollectionsFolder(grok.Container):
+ pass
+
+class QuickNameChooser(grok.Adapter, NameChooser):
+ """INameChooser adapter to generate sequential numeric ids without
+ resorting to a linear search."""
+ grok.context(grok.Container)
+ implements(INameChooser)
+
+ def nextId(self,fmt='%s'):
+ """Binary search to quickly find an unused numbered key.
+
+ This was designed to scale well when importing large batches of books
+ without ISBN, while keeping the ids short.
+
+ The algorithm generates a key right after the largest numbered key or
+ in some unused lower numbered slot found by the second loop.
+
+ If keys are later deleted in random order, some of the resulting slots
+ will be reused and some will not.
+ """
+ i = 1
+ while fmt%i in self.context:
+ i *= 2
+ blank = i
+ full = i//2
+ while blank > (full+1):
+ i = (blank+full)//2
+ if fmt%i in self.context:
+ full = i
+ else:
+ blank = i
+ return fmt%blank
+
+ def chooseName(self, name, object):
+ name = name or self.nextId('k%04d')
+ # Note: potential concurrency problems of nextId are (hopefully)
+ # handled by calling the super.QuickNameChooser
+ return super(QuickNameChooser, self).chooseName(name, object)
+
\ No newline at end of file
Modified: Sandbox/luciano/kirbi/src/kirbi/copy.py
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/copy.py 2007-08-18 20:43:31 UTC (rev 78971)
+++ Sandbox/luciano/kirbi/src/kirbi/copy.py 2007-08-18 22:30:11 UTC (rev 78972)
@@ -15,22 +15,18 @@
"""
import grok
-from interfaces import ICopy, ILease
+from interfaces import IItem, ILease
from zope.interface import Interface, implements, invariant
from zope import schema
-class Copy(grok.Container):
+class Item(grok.Container):
"""An exemplar of a book.
- A copy is associated to a Book instance.
-
- A copy can contain Lease instances, recording each time it was lent.
- When a copy is transferred or deleted, the lease history automatically
- goes with it.
+ See note at interfaces.IItem.
"""
- implements(ICopy)
+ implements(IItem)
- def __init__(self, book_id):
+ def __init__(self, manifestation_id):
super(User, self).__init__()
Modified: Sandbox/luciano/kirbi/src/kirbi/interfaces.py
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/interfaces.py 2007-08-18 20:43:31 UTC (rev 78971)
+++ Sandbox/luciano/kirbi/src/kirbi/interfaces.py 2007-08-18 22:30:11 UTC (rev 78972)
@@ -88,10 +88,34 @@
if (not book.title or not book.title.strip()) and (not book.isbn):
raise Invalid(u'Either the title or the ISBN must be given.')
-class ICopy(Interface):
- """An exemplar of a book."""
+class IItem(Interface):
+ """A physical exemplar of a manifestation (book, DVD or other medium).
- book_id = schema.TextLine(title=u"Book id",
+ The terms ``ìtem`` and ``manifestation`` are borrowed from the terminology
+ of the FRBR - `Functional Requirements for Bibliographic Records`__.
+
+ __ http://www.ifla.org/VII/s13/frbr/frbr.htm
+
+ The FRBR defines these relationships::
+
+ work >---is realized through---> expression
+ expression >---is embodied in---> manifestation
+ manifestation >---is exemplified by---> item
+
+ For example, Hamlet is a work by Shakespeare, and has many expressions:
+ the written text of the play, performances, movies etc. A particular
+ rendition of the written text is an expression. A specific edition of an
+ expression is a manifestation (commonly identified by an ISBN). An exemplar
+ of a manifestation is an item, a physical book that sits in a shelf and
+ can be borrowed.
+
+ Currently, Kirbi supports only one kind of manifestation: books.
+ So identifiers embedded in code use the term ``manifestation`` but
+ user-visible strings use ``book`` for now.
+
+ """
+
+ manifestation_id = schema.TextLine(title=u"Book id",
description=u"The id of the book of which this is a copy.",
required=True)
description = schema.Text(title=u"Description",
@@ -103,6 +127,15 @@
description=u"Date when added to your collection.",
required=False)
+class ICollection(Interface):
+ """A collection of Items belonging to a User"""
+ title = schema.TextLine(title=u"Title",
+ description=u"The full name of the user who owns the collection.",
+ required=True)
+ private = schema.Bool(title=u"Private",
+ description=u"If true, items will not appear in public searches.",
+ default=True)
+
class ILease(Interface):
"""A book lease."""
Modified: Sandbox/luciano/kirbi/src/kirbi/pac.py
===================================================================
--- Sandbox/luciano/kirbi/src/kirbi/pac.py 2007-08-18 20:43:31 UTC (rev 78971)
+++ Sandbox/luciano/kirbi/src/kirbi/pac.py 2007-08-18 22:30:11 UTC (rev 78972)
@@ -16,7 +16,6 @@
import grok
from book import Book, IBook
-from zope.app.container.contained import NameChooser as BaseNameChooser
from zope.app.container.interfaces import INameChooser
from zope.interface import implements
from zope.lifecycleevent import modified, Attributes
@@ -213,40 +212,6 @@
def pendingIsbns(self):
return list(self.sortedByTime(self.context.getPending()))
-class NameChooser(grok.Adapter, BaseNameChooser):
- implements(INameChooser)
-
- def nextId(self,fmt='%s'):
- """Binary search to quickly find an unused numbered key.
-
- This was designed to scale well when importing large batches of books
- without ISBN, while keeping the ids short.
-
- The algorithm generates a key right after the largest numbered key or
- in some unused lower numbered slot found by the second loop.
-
- If keys are later deleted in random order, some of the resulting slots
- will be reused and some will not.
- """
- i = 1
- while fmt%i in self.context:
- i *= 2
- blank = i
- full = i//2
- while blank > (full+1):
- i = (blank+full)//2
- if fmt%i in self.context:
- full = i
- else:
- blank = i
- return fmt%blank
-
- def chooseName(self, name, object):
- name = name or self.nextId('k%04d')
- # Note: potential concurrency problems of nextId are (hopefully)
- # handled by calling the super.NameChooser
- return super(NameChooser, self).chooseName(name, object)
-
class PacRPC(grok.XMLRPC):
def list(self):
@@ -262,8 +227,6 @@
def dumpIncomplete(self):
return self.context.dumpIncomplete()
-
-
class ImportDemo(grok.View):
def render(self):
More information about the Checkins
mailing list