From d5585bbe9e1db175cfd1c9975810b9ddaf21a4ba Mon Sep 17 00:00:00 2001 From: Sylvain Viollon Date: Thu, 15 Oct 2009 13:17:09 +0200 Subject: [PATCH] Import code into git. --- .gitignore | 12 ++ README.txt | 38 ++++++ bootstrap.py | 55 +++++++++ buildout.cfg | 8 ++ docs/HISTORY.txt | 23 ++++ setup.cfg | 3 + setup.py | 50 ++++++++ zeam/__init__.py | 6 + zeam/utils/__init__.py | 6 + zeam/utils/batch/__init__.py | 2 + zeam/utils/batch/batch.py | 117 +++++++++++++++++++ zeam/utils/batch/batch.txt | 117 +++++++++++++++++++ zeam/utils/batch/browser/__init__.py | 0 zeam/utils/batch/browser/configure.zcml | 30 +++++ zeam/utils/batch/browser/templates/batch.pt | 27 +++++ zeam/utils/batch/browser/views.py | 109 +++++++++++++++++ zeam/utils/batch/browser/views.txt | 116 ++++++++++++++++++ zeam/utils/batch/configure.zcml | 16 +++ zeam/utils/batch/ftesting.zcml | 8 ++ zeam/utils/batch/i18n/en/LC_MESSAGES/zeam.mo | Bin 0 -> 416 bytes zeam/utils/batch/i18n/en/LC_MESSAGES/zeam.po | 20 ++++ zeam/utils/batch/i18n/fr/LC_MESSAGES/zeam.mo | Bin 0 -> 490 bytes zeam/utils/batch/i18n/fr/LC_MESSAGES/zeam.po | 20 ++++ zeam/utils/batch/i18n/nl/LC_MESSAGES/zeam.mo | Bin 0 -> 486 bytes zeam/utils/batch/i18n/nl/LC_MESSAGES/zeam.po | 20 ++++ zeam/utils/batch/i18n/zeam.pot | 20 ++++ zeam/utils/batch/interfaces.py | 55 +++++++++ zeam/utils/batch/tests.py | 41 +++++++ 28 files changed, 919 insertions(+) create mode 100644 .gitignore create mode 100644 README.txt create mode 100644 bootstrap.py create mode 100644 buildout.cfg create mode 100644 docs/HISTORY.txt create mode 100644 setup.cfg create mode 100644 setup.py create mode 100644 zeam/__init__.py create mode 100644 zeam/utils/__init__.py create mode 100644 zeam/utils/batch/__init__.py create mode 100644 zeam/utils/batch/batch.py create mode 100644 zeam/utils/batch/batch.txt create mode 100644 zeam/utils/batch/browser/__init__.py create mode 100644 zeam/utils/batch/browser/configure.zcml create mode 100644 zeam/utils/batch/browser/templates/batch.pt create mode 100644 zeam/utils/batch/browser/views.py create mode 100644 zeam/utils/batch/browser/views.txt create mode 100644 zeam/utils/batch/configure.zcml create mode 100644 zeam/utils/batch/ftesting.zcml create mode 100644 zeam/utils/batch/i18n/en/LC_MESSAGES/zeam.mo create mode 100644 zeam/utils/batch/i18n/en/LC_MESSAGES/zeam.po create mode 100644 zeam/utils/batch/i18n/fr/LC_MESSAGES/zeam.mo create mode 100644 zeam/utils/batch/i18n/fr/LC_MESSAGES/zeam.po create mode 100644 zeam/utils/batch/i18n/nl/LC_MESSAGES/zeam.mo create mode 100644 zeam/utils/batch/i18n/nl/LC_MESSAGES/zeam.po create mode 100644 zeam/utils/batch/i18n/zeam.pot create mode 100644 zeam/utils/batch/interfaces.py create mode 100644 zeam/utils/batch/tests.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5443a8f --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +# git-ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +*~ +*.pyc +*.egg-info +.installed.cfg +bin/ +parts/ +develop-eggs/ diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..ee40720 --- /dev/null +++ b/README.txt @@ -0,0 +1,38 @@ +zeam.utils.batch +================ + +This package provides a batch functionality for Zope 2 and Zope 3. + +You can use it like that: + +1. Your container which is going to handle the batch must implements + the marker interface ``zeam.utils.batch.interfaces.IBatchedContent``. + +2. You create your batch object in your view code:: + + from zope.component import queryMultiAdapter + from zeam.utils.batch import batch + from zeam.utils.batch.interfaces import IBatchView + + + class MyViewClass(...): + + def update(self): + fulllist = ... + self.myitems = batch(fulllist, count=10, name='myitems', request=self.request) + self.batch = queryMultiAdapter((self.context, self.myitems, self.request), + IBatchView)() + + +3. You use it in your template:: + + + + + ... + + + + +That's it. + diff --git a/bootstrap.py b/bootstrap.py new file mode 100644 index 0000000..1bfffe3 --- /dev/null +++ b/bootstrap.py @@ -0,0 +1,55 @@ +############################################################################## +# +# Copyright (c) 2006 Zope Corporation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# +############################################################################## +"""Bootstrap a buildout-based project + +Simply run this script in a directory containing a buildout.cfg. +The script accepts buildout command-line options, so you can +use the -c option to specify an alternate configuration file. + +$Id$ +""" + +import os, shutil, sys, tempfile, urllib2 + +tmpeggs = tempfile.mkdtemp() + +try: + import pkg_resources +except ImportError: + ez = {} + exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py' + ).read() in ez + ez['use_setuptools'](to_dir=tmpeggs, download_delay=0) + + import pkg_resources + +cmd = 'from setuptools.command.easy_install import main; main()' +if sys.platform == 'win32': + cmd = '"%s"' % cmd # work around spawn lamosity on windows + +ws = pkg_resources.working_set +assert os.spawnle( + os.P_WAIT, sys.executable, sys.executable, + '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout', + dict(os.environ, + PYTHONPATH= + ws.find(pkg_resources.Requirement.parse('setuptools')).location + ), + ) == 0 + +ws.add_entry(tmpeggs) +ws.require('zc.buildout') +import zc.buildout.buildout +zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap']) +shutil.rmtree(tmpeggs) diff --git a/buildout.cfg b/buildout.cfg new file mode 100644 index 0000000..efa90ad --- /dev/null +++ b/buildout.cfg @@ -0,0 +1,8 @@ +[buildout] +develop = . +parts = test + +[test] +recipe = zc.recipe.testrunner +eggs = zeam.utils.batch [test] +defaults = ['-v', '-c', '-s', 'zeam.utils.batch'] diff --git a/docs/HISTORY.txt b/docs/HISTORY.txt new file mode 100644 index 0000000..62d5b58 --- /dev/null +++ b/docs/HISTORY.txt @@ -0,0 +1,23 @@ +Changelog +========= + +0.4 (unreleased) +---------------- + +* You adapt the batch with the view on which you display the batch: + its name will keep when generating links, +* Batch can be *disabled* with a count of 0, +* Add translations for french, english and dutch. + +0.3 (2008/10/18) +---------------- + +* Fix and add tests, +* Don't display batch navigation if everything fits on one page, +* No more special links are generated for the first page of the batch. + +0.2 +--- + +* Initial release + diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..01bb954 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,3 @@ +[egg_info] +tag_build = dev +tag_svn_revision = true diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..baf4847 --- /dev/null +++ b/setup.py @@ -0,0 +1,50 @@ +from setuptools import setup, find_packages +import os + +version = '0.4' + +install_requires=[ + 'setuptools', + 'zope.interface', + 'zope.schema', + 'zope.annotation', + 'zope.traversing', + 'zope.app.pagetemplate', + 'zope.cachedescriptors', + ] + +tests_requires = install_requires + [ + 'zope.testing', + 'zope.app.testing', + 'zope.app.securitypolicy', + 'zope.app.zcmlfiles', + 'zope.app.zptpage', + ], + + +setup(name='zeam.utils.batch', + version=version, + description="Generic Batch support for Zope", + long_description=open("README.txt").read() + "\n" + + open(os.path.join("docs", "HISTORY.txt")).read(), + classifiers=[ + "Framework :: Zope2", + "Framework :: Zope3", + "Programming Language :: Python", + "Topic :: Software Development :: Libraries :: Python Modules", + "License :: OSI Approved :: BSD License", + ], + keywords='batch zope', + author='Sylvain Viollon', + author_email='thefunny@gmail.com', + url='', + license='BSD', + packages=find_packages(exclude=['ez_setup']), + namespace_packages=['zeam', 'zeam.utils'], + include_package_data=True, + zip_safe=False, + test_suite='zeam.utils.batch', + tests_require = tests_requires, + install_requires=install_requires, + extras_require = {'test': tests_requires}, + ) diff --git a/zeam/__init__.py b/zeam/__init__.py new file mode 100644 index 0000000..f48ad10 --- /dev/null +++ b/zeam/__init__.py @@ -0,0 +1,6 @@ +# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages +try: + __import__('pkg_resources').declare_namespace(__name__) +except ImportError: + from pkgutil import extend_path + __path__ = extend_path(__path__, __name__) diff --git a/zeam/utils/__init__.py b/zeam/utils/__init__.py new file mode 100644 index 0000000..f48ad10 --- /dev/null +++ b/zeam/utils/__init__.py @@ -0,0 +1,6 @@ +# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages +try: + __import__('pkg_resources').declare_namespace(__name__) +except ImportError: + from pkgutil import extend_path + __path__ = extend_path(__path__, __name__) diff --git a/zeam/utils/batch/__init__.py b/zeam/utils/batch/__init__.py new file mode 100644 index 0000000..0cfa430 --- /dev/null +++ b/zeam/utils/batch/__init__.py @@ -0,0 +1,2 @@ + +from batch import batch diff --git a/zeam/utils/batch/batch.py b/zeam/utils/batch/batch.py new file mode 100644 index 0000000..6e008c1 --- /dev/null +++ b/zeam/utils/batch/batch.py @@ -0,0 +1,117 @@ +# Copyright Sylvain Viollon 2008 (c) +# $Id: batch.py 94 2008-10-20 22:20:34Z sylvain $ + +from zope.interface import implements + +from interfaces import IBatch + +class batchBaseIterator(object): + """An iterator on batch object. + """ + + def __init__(self, context): + self.context = context + self.start = 0 + + def __iter__(self): + return self + + +class batchItemIterator(batchBaseIterator): + """Return the next object in the batch iterator. + """ + + def next(self): + try: + elt = self.context[self.start] + except IndexError: + raise StopIteration + self.start += 1 + return elt + +class batchIndiceIterator(batchBaseIterator): + """Return the next indice in the batch iterator. + """ + + def next(self): + last = self.context.last + if not last: + raise StopIteration + if self.start < last: + value = self.start + self.start += self.context.count + return (value, value / self.context.count + 1) + raise StopIteration + + +class batch(object): + """A simple batch object. + """ + + implements(IBatch) + + def __init__(self, collection, start=0, count=10, name='', request=None): + if not (request is None): + key = 'bstart' + if name: + key += '_' + name + start = int(request.form.get(key, 0)) + self.start = start + self.count = count + self.data = collection + self.name = name + + def _setData(self, data): + self._data = data + self._end = len(self._data) + if not self.count or self.count > self._end: + self._max = self._end + else: + self._max = self.count + + def _getData(self): + return self._data + + data = property(_getData, _setData) + + def __getitem__(self, index): + if index < 0 or index >= self._max: + raise IndexError, "invalid index" + return self.data[self.start + index] + + def batchLen(self): + if not self.count: + return 0 + last = self._end % self.count + if last: + last = 1 + return (self._end / self.count) + last + + def __iter__(self): + return batchItemIterator(self) + + def all(self): + return batchIndiceIterator(self) + + @property + def first(self): + return 0 + + @property + def previous(self): + previous = self.start - self.count + if previous < 0: + return None + return previous + + @property + def last(self): + return self.batchLen() * self.count + + @property + def next(self): + next = self.start + self.count + if next >= self.last: + return None + return next + diff --git a/zeam/utils/batch/batch.txt b/zeam/utils/batch/batch.txt new file mode 100644 index 0000000..ee9074b --- /dev/null +++ b/zeam/utils/batch/batch.txt @@ -0,0 +1,117 @@ +Batch +----- + +Batch support for Zope3 : + + >>> from zeam.utils.batch.batch import batch + >>> l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] + >>> b = batch(l, count=4) + +This verify the provided interface: + + >>> from zope.interface.verify import verifyObject + >>> from zeam.utils.batch.interfaces import IBatch + >>> verifyObject(IBatch, b) + True + +Now test access : + + >>> b[0] + 1 + >>> b[3] + 4 + >>> b[4] + Traceback (most recent call last): + File "", line 1, in ? + File "/Users/sylvain/z8080/lib/python/utils/app/batch/batch.py", line 50, in __getitem__ + raise IndexError, "invalid index" + IndexError: invalid index + >>> for n in b: + ... print n + 1 + 2 + 3 + 4 + +Test a batch with a start value : + + >>> b = batch(l, start=4, count=4) + +And access on it : + + >>> b[0] + 5 + >>> b[3] + 8 + >>> b[4] + Traceback (most recent call last): + File "", line 1, in ? + File "utils/app/batch/batch.py", line 50, in __getitem__ + raise IndexError, "invalid index" + IndexError: invalid index + + +Negative index are forbidden : + + >>> b[-1] + Traceback (most recent call last): + File "", line 1, in ? + File "utils/app/batch/batch.py", line 50, in __getitem__ + raise IndexError, "invalid index" + IndexError: invalid index + +And test iterator on this one : + + >>> for n in b: + ... print n + 5 + 6 + 7 + 8 + +Test batch methods : + + >>> b.first + 0 + >>> b.last + 12 + >>> for i in b.all(): + ... print i + (0, 1) + (4, 2) + (8, 3) + >>> b.batchLen() + 3 + +Test end of list iteration : + + >>> b = batch(l, start=8, count=4) + >>> for n in b: + ... print n + 9 + 0 + +Test empty batch : + + >>> b = batch([]) + >>> for n in b.all(): + ... print n + >>> b.first + 0 + >>> b.last + 0 + >>> b.batchLen() + 0 + +And a batch with one element: + + >>> b = batch(['a',]) + >>> for n in b.all(): + ... print n + (0, 1) + >>> b.first + 0 + >>> b.last + 10 + >>> b.batchLen() + 1 diff --git a/zeam/utils/batch/browser/__init__.py b/zeam/utils/batch/browser/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/zeam/utils/batch/browser/configure.zcml b/zeam/utils/batch/browser/configure.zcml new file mode 100644 index 0000000..fdb50ad --- /dev/null +++ b/zeam/utils/batch/browser/configure.zcml @@ -0,0 +1,30 @@ + + + + + + + + + diff --git a/zeam/utils/batch/browser/templates/batch.pt b/zeam/utils/batch/browser/templates/batch.pt new file mode 100644 index 0000000..6591c6d --- /dev/null +++ b/zeam/utils/batch/browser/templates/batch.pt @@ -0,0 +1,27 @@ + + + diff --git a/zeam/utils/batch/browser/views.py b/zeam/utils/batch/browser/views.py new file mode 100644 index 0000000..c9a929b --- /dev/null +++ b/zeam/utils/batch/browser/views.py @@ -0,0 +1,109 @@ +# Copyright Sylvain Viollon 2008 (c) +# $Id: views.py 96 2008-10-20 22:25:04Z sylvain $ + +from zope.interface import implements +from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile +from zope.traversing.interfaces import ITraversable +from zope.traversing.browser import absoluteURL + +import zope.cachedescriptors.property + +from zeam.utils.batch.interfaces import IBatchView + +class baseView(object): + + def __init__(self, context, request): + self.context = context + self.request = request + +class batchView(baseView): + """View object on batched elements. + """ + + implements(IBatchView) + + render = ViewPageTemplateFile('templates/batch.pt') + + def __init__(self, context, batch, request): + super(batchView, self).__init__(context, request) + self._batch = batch + + @zope.cachedescriptors.property.CachedProperty + def contextURL(self): + return absoluteURL(self.context, self.request) + + def _baseLink(self, position): + if not position: + return self.contextURL + if self._batch.name: + base = '%s/++batch++%s+%d' + return base % (self.contextURL, self._batch.name, position) + return '%s/++batch++%d' % (self.contextURL, position) + + @property + def batch(self): + end = self._batch.batchLen() + if end > 1: + count = 0 + wanted = self._batch.start / self._batch.count + ldots = False + for pos, item in self._batch.all(): + if (((count > 2) and (count < (wanted - 3))) or + ((count < (end - 3)) and (count > (wanted + 3)))): + if not ldots: + ldots = True + yield dict(name=None, url=None, style=None) + + else: + ldots = False + url_item = self._baseLink(pos) + current_item = (pos == self._batch.start) + style = current_item and 'current' or None + yield dict(name=item, url=url_item, style=style) + count += 1 + + @property + def previous(self): + previous = self._batch.previous + avail = not (previous is None) + return avail and self._baseLink(previous) or None + + @property + def next(self): + next = self._batch.next + avail = not (next is None) + return avail and self._baseLink(next) or None + + def __call__(self): + return self.render() + + +class batchNamedView(batchView): + """View on batched elements: keep the view name in generated + links. + """ + + def __init__(self, context, batch, request, view): + super(batchNamedView, self).__init__(context, batch, request) + self._view = view + + def _baseLink(self, position): + link = super(batchNamedView, self)._baseLink(position) + return link + '/@@' + self._view.__name__ + + +class batchNamespace(baseView): + """Make batch works with namespace. + """ + + implements(ITraversable) + + def traverse(self, name, ignored): + if '+' in name: + key, value = name.split('+') + key = 'bstart_' + key + else: + key = 'bstart' + value = name + self.request.form[key] = value + return self.context diff --git a/zeam/utils/batch/browser/views.txt b/zeam/utils/batch/browser/views.txt new file mode 100644 index 0000000..9d14410 --- /dev/null +++ b/zeam/utils/batch/browser/views.txt @@ -0,0 +1,116 @@ +Batch navigation +---------------- + +First we need a content to apply the batch on:: + + >>> from zope.interface import implements + >>> from persistent import Persistent + >>> from zeam.utils.batch.interfaces import IBatchedContent + >>> class Content(Persistent): + ... implements(IBatchedContent) + >>> app = getRootFolder() + >>> app['content'] = Content() + >>> content = app['content'] + >>> IBatchedContent.providedBy(content) + True + +After we need a batch:: + + >>> from zeam.utils.batch.batch import batch + >>> list_long = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] + >>> b = batch(list_long, count=4) + +And a request:: + + >>> from zope.publisher.browser import TestRequest + >>> request = TestRequest() + +So we can get the view:: + + >>> from zope.component import queryMultiAdapter + >>> from zeam.utils.batch.interfaces import IBatchView + >>> view = queryMultiAdapter((content, b, request), IBatchView) + >>> view + + >>> from zope.interface.verify import verifyObject + >>> verifyObject(IBatchView, view) + True + +We are on the first page, start is 0:: + + >>> view.previous + >>> view.next + 'http://127.0.0.1/content/++batch++4' + >>> for b in view.batch: + ... print b + {'url': 'http://127.0.0.1/content', 'style': 'current', 'name': 1} + {'url': 'http://127.0.0.1/content/++batch++4', 'style': None, 'name': 2} + {'url': 'http://127.0.0.1/content/++batch++8', 'style': None, 'name': 3} + +We set start to 4:: + + >>> b = batch(list_long, start=4, count=4) + >>> view = queryMultiAdapter((content, b, request), IBatchView) + >>> view.previous + 'http://127.0.0.1/content' + >>> view.next + 'http://127.0.0.1/content/++batch++8' + >>> for b in view.batch: + ... print b + {'url': 'http://127.0.0.1/content', 'style': None, 'name': 1} + {'url': 'http://127.0.0.1/content/++batch++4', 'style': 'current', 'name': 2} + {'url': 'http://127.0.0.1/content/++batch++8', 'style': None, 'name': 3} + +We set start to 8, last page:: + + >>> b = batch(list_long, start=8, count=4) + >>> view = queryMultiAdapter((content, b, request), IBatchView) + >>> view.previous + 'http://127.0.0.1/content/++batch++4' + >>> view.next + >>> for b in view.batch: + ... print b + {'url': 'http://127.0.0.1/content', 'style': None, 'name': 1} + {'url': 'http://127.0.0.1/content/++batch++4', 'style': None, 'name': 2} + {'url': 'http://127.0.0.1/content/++batch++8', 'style': 'current', 'name': 3} + +Now we have less than one page:: + + >>> b = batch(['a', 'b',], count=4) + >>> view = queryMultiAdapter((content, b, request), IBatchView) + >>> view.previous + >>> view.next + >>> for b in view.batch: + ... print b + +The number of item is modulo to the size of the batch:: + + >>> list_short = [1, 2, 3, 4, 5, 6, 7, 8] + >>> b = batch(list_short, start=4, count=4) + >>> view = queryMultiAdapter((content, b, request), IBatchView) + >>> view.previous + 'http://127.0.0.1/content' + >>> view.next + >>> for b in view.batch: + ... print b + {'url': 'http://127.0.0.1/content', 'style': None, 'name': 1} + {'url': 'http://127.0.0.1/content/++batch++4', 'style': 'current', 'name': 2} + +If you put a name, it's inserted in the link:: + + >>> b = batch(list_long, start=4, count=4, name='video') + >>> view = queryMultiAdapter((content, b, request), IBatchView) + >>> view.previous + 'http://127.0.0.1/content' + >>> view.next + 'http://127.0.0.1/content/++batch++video+8' + >>> for b in view.batch: + ... print b + {'url': 'http://127.0.0.1/content', 'style': None, 'name': 1} + {'url': 'http://127.0.0.1/content/++batch++video+4', 'style': 'current', 'name': 2} + {'url': 'http://127.0.0.1/content/++batch++video+8', 'style': None, 'name': 3} + + +Tear down: + + >>> sync() diff --git a/zeam/utils/batch/configure.zcml b/zeam/utils/batch/configure.zcml new file mode 100644 index 0000000..f0fc39a --- /dev/null +++ b/zeam/utils/batch/configure.zcml @@ -0,0 +1,16 @@ + + + + + + + + + + + diff --git a/zeam/utils/batch/ftesting.zcml b/zeam/utils/batch/ftesting.zcml new file mode 100644 index 0000000..2d04c9f --- /dev/null +++ b/zeam/utils/batch/ftesting.zcml @@ -0,0 +1,8 @@ + + + + + + diff --git a/zeam/utils/batch/i18n/en/LC_MESSAGES/zeam.mo b/zeam/utils/batch/i18n/en/LC_MESSAGES/zeam.mo new file mode 100644 index 0000000000000000000000000000000000000000..dcea02b377118102c3b5dc9604df7236dc1084eb GIT binary patch literal 416 zcmYL_K~KUk6vs7s+R?Lz9=u`M*ul(-gb72JY>dD#>cy1u2G!9nT_NK4@ay?md`pP@ zlVAFh_wRfC_xIxb=LB_%Tq0M<8FGy@3XlSuw|F+5e@%@30AXpoq|ab#sTCs&ZpE5d zvsIsyET;nl++u?cxdld2tw<&;@jc@E%)en?fVCGmlZ;MbCz}}u>uVHFX`0btNS-p5 z#;vz(961TEEzJ#Ab;+$ZjEv?4fcMX zk7#i8HSa6H&`1frlxoFDu#nbyp^u=z;7=^+!=90EU4hH1%C(0;nEt(xCDbnNFkIMn IwRcYb0IAP;l>h($ literal 0 HcmV?d00001 diff --git a/zeam/utils/batch/i18n/en/LC_MESSAGES/zeam.po b/zeam/utils/batch/i18n/en/LC_MESSAGES/zeam.po new file mode 100644 index 0000000..2f87f37 --- /dev/null +++ b/zeam/utils/batch/i18n/en/LC_MESSAGES/zeam.po @@ -0,0 +1,20 @@ +msgid "" +msgstr "" +"Project-Id-Version: batch trunk" +"POT-Creation-Date: Mon Oct 20 22:26:08 2008\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Silva Translators \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generated-By: zope/app/translation_files/extract.py\n" + +#: /browser/templates/batch.pt:22 +msgid "Next" +msgstr "" + +#: /browser/templates/batch.pt:6 +msgid "Previous" +msgstr "" + diff --git a/zeam/utils/batch/i18n/fr/LC_MESSAGES/zeam.mo b/zeam/utils/batch/i18n/fr/LC_MESSAGES/zeam.mo new file mode 100644 index 0000000000000000000000000000000000000000..90e86e648ddffd7f15368d23aef82f08c04e8600 GIT binary patch literal 490 zcmYL_%}&BV5P+*_z*k?@8FSV zaY{&-?6)(Sot?kkb?MhaIYVxcTjU%GkwQL@62g#6WKwWqSqk+9@`v^n>K$r4dpX6s z$hVgsd>d<^VI|ZuM?-xAH?*75SJ1go(kEkP_>366lwX5>LR%V`!3WxA27D4JN&4In z*CDR!yLZ0hq3w9~pihUGwa9S@E!?!`&_n2b*+GvTvfR)_GnvnsQQ9Y+Q5ce5GYUvO zh??E-so8E1gE($rsGKg@6lel$;geX*SBxCL=A;f<@Up0R@=3^vW>Dd3(XgX#6ddQN zRUEseqydR_*BQ=Wa0k_F&V+m*e8zMR=5dsCsCSGj`kR2Jf#fO`a_SRrER6j|UqFJ! xO{DaB?UNssL6v1$)f@)G>E9<}4tW)8XvR$?TiaH=6e}i+y>B;syGgMX>mNi+h_(O# literal 0 HcmV?d00001 diff --git a/zeam/utils/batch/i18n/fr/LC_MESSAGES/zeam.po b/zeam/utils/batch/i18n/fr/LC_MESSAGES/zeam.po new file mode 100644 index 0000000..2ef89d9 --- /dev/null +++ b/zeam/utils/batch/i18n/fr/LC_MESSAGES/zeam.po @@ -0,0 +1,20 @@ +msgid "" +msgstr "" +"Project-Id-Version: batch trunk" +"POT-Creation-Date: Mon Oct 20 22:26:08 2008\n" +"PO-Revision-Date: 2008-10-20 22:27+0200\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Silva Translators \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generated-By: zope/app/translation_files/extract.py\n" + +#: /browser/templates/batch.pt:22 +msgid "Next" +msgstr "Suivant" + +#: /browser/templates/batch.pt:6 +msgid "Previous" +msgstr "Précédent" + diff --git a/zeam/utils/batch/i18n/nl/LC_MESSAGES/zeam.mo b/zeam/utils/batch/i18n/nl/LC_MESSAGES/zeam.mo new file mode 100644 index 0000000000000000000000000000000000000000..faea397c0704b43a5cd0bc307d2015c1f11f8a41 GIT binary patch literal 486 zcmYL_-%r9Y5XYyYF?;mchrW}t9~!evBp?h!vH^iXeABWWqdMB9D@6Q1{MUTcf5jV; zaOtQ0_IkbR_2;VgWuToQ*T^k$j)X{MuSgAH$R)C@I57-)*ngwGK>dp=j=i1YT;kZ3wc=^RwarSQpu>10K;+KBh@D5hNnOydFVF%3S6q#&b26W1oL z>$`Wp?V+|kb3CFG%v$9*gjR0q*z`a2#;M!rF+)~r8Y?EsoN1|i(w~JP8Fr$8G=r!! z2-}@rZxT$WEesXehGjrwU~8XDdA?=jc(o)=P&}z~#}jQXmWn|mk?WQj4Wi)KkJGTt zt`r&s*4-7@gT_CwikxwAPm&c=CFqA)+^60#u6o}R6b(coQ!X-}cnhx0XZi#J6#hg? qA9p_alm%F\n" +"Language-Team: Silva Translators \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generated-By: zope/app/translation_files/extract.py\n" + +#: /browser/templates/batch.pt:22 +msgid "Next" +msgstr "Volgende" + +#: /browser/templates/batch.pt:6 +msgid "Previous" +msgstr "Vorige" + diff --git a/zeam/utils/batch/i18n/zeam.pot b/zeam/utils/batch/i18n/zeam.pot new file mode 100644 index 0000000..2f87f37 --- /dev/null +++ b/zeam/utils/batch/i18n/zeam.pot @@ -0,0 +1,20 @@ +msgid "" +msgstr "" +"Project-Id-Version: batch trunk" +"POT-Creation-Date: Mon Oct 20 22:26:08 2008\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Silva Translators \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generated-By: zope/app/translation_files/extract.py\n" + +#: /browser/templates/batch.pt:22 +msgid "Next" +msgstr "" + +#: /browser/templates/batch.pt:6 +msgid "Previous" +msgstr "" + diff --git a/zeam/utils/batch/interfaces.py b/zeam/utils/batch/interfaces.py new file mode 100644 index 0000000..ac1e41b --- /dev/null +++ b/zeam/utils/batch/interfaces.py @@ -0,0 +1,55 @@ +# Copyright Sylvain Viollon 2008 (c) +# $Id: interfaces.py 86 2008-10-18 00:20:21Z sylvain $ + +from zope import interface +from zope.annotation.interfaces import IAttributeAnnotatable +from zope import schema + +class IBatch(interface.Interface): + """A batch object. + """ + + start = schema.Int( + title=u"Starting indice over the batch") + count = schema.Int( + title=u"Number of element in a batch") + data = schema.List( + title=u"Data to be batched") + name = schema.TextLine( + title=u"Name of the batch", + required=False, + default=u"") + + first = interface.Attribute("First element") + last = interface.Attribute("Last element") + previous = interface.Attribute("Previous index or None") + next = interface.Attribute("Next index or None") + + def __getitem__(index): + """Return item at index. + """ + + def __iter__(): + """Return an iterator on batched content. + """ + + def all(): + """Return an interator on all (index, starting element) of the + batch. + """ + + def batchLen(): + """Return the number of available index in the batch. + """ + +class IBatchView(interface.Interface): + """Used to render a batch. + """ + + next = interface.Attribute("Link to the next page or None") + previous = interface.Attribute("Link to the previous page or None") + batch = interface.Attribute("List of links to each page, which is current") + +class IBatchedContent(IAttributeAnnotatable): + """Marker interface for content with batched data. + """ diff --git a/zeam/utils/batch/tests.py b/zeam/utils/batch/tests.py new file mode 100644 index 0000000..c3cba47 --- /dev/null +++ b/zeam/utils/batch/tests.py @@ -0,0 +1,41 @@ +# Copyright Sylvain Viollon 2008 (c) +# $Id: tests.py 85 2008-10-18 00:15:41Z sylvain $ + +from zope.testing import doctest +from zope.testing.doctest import DocFileSuite +from zope.app.testing.functional import FunctionalTestSetup, ZCMLLayer, \ + HTTPCaller, getRootFolder, sync + +import zeam.utils.batch +import unittest, os + +config = os.path.join(os.path.dirname(zeam.utils.batch.__file__), + 'ftesting.zcml') +FunctionalLayer = ZCMLLayer(config, __name__, 'FunctionalLayer', + allow_teardown=True) + +def setUp(test): + FunctionalTestSetup().setUp() + +def tearDown(test): + FunctionalTestSetup().tearDown() + +options=(doctest.ELLIPSIS+ + doctest.NORMALIZE_WHITESPACE+ + doctest.REPORT_NDIFF) + +def test_suite(): + batchs = DocFileSuite('batch.txt', + optionflags=options) + views = DocFileSuite(os.path.join('browser', 'views.txt'), + globs=dict(http=HTTPCaller(), + getRootFolder=getRootFolder, + sync=sync), + optionflags=options) + views.layer = FunctionalLayer + + suite = unittest.TestSuite() + suite.addTest(batchs) + suite.addTest(views) + return suite +