I added a new project called pluggablecatalog to the collective.
pluggablecatalog is a replacement (or rather: a wrapper) for Plone's portal catalog. It adds the ability to plug in default search restrictions without the need to subclass or monkey- patch the catalog.
From the docstring of pluggablecatalog/tool.py:
Wraps CMFPlone's CatalogTool to add default parameters
collected from IQueryDefaults utilities.
>>> from Products.pluggablecatalog.tool import CatalogTool
>>> catalog = self.portal.portal_catalog
>>> isinstance(catalog, CatalogTool)
True
We create two documents and make sure they're indexed:
>>> len(catalog())
0
>>> self.folder.invokeFactory('Document', 'doc1')
'doc1'
>>> self.folder.invokeFactory('Document', 'doc2')
'doc2'
>>> doc1, doc2 = self.folder.doc1, self.folder.doc2
>>> doc1.setTitle('First Document')
>>> doc2.setTitle('Second Document')
>>> doc1.reindexObject(); doc2.reindexObject()
>>> len(catalog())
2
Let's now add a rather stupid IQueryDefaults utility that
restricts searches by default to objects with the Title 'First
Document':
>>> from zope import component
>>> from zope import interface
>>> from Products.pluggablecatalog.interfaces import IQueryDefaults
>>> def myDefaults(context, request):
... return {'Title': 'First Document'}
>>> interface.directlyProvides(myDefaults, IQueryDefaults)
>>> component.getService('Utilities').provideUtility(
... IQueryDefaults, myDefaults)
With this utility in place, we should only retrieve doc1 now,
unless we explicitly provide a 'Title' query parameter:
>>> len(catalog())
1
>>> catalog()[0].getObject().aq_base is doc1.aq_base
True
>>> len(catalog(Title='Second Document'))
1
>>> (catalog(Title='Second Document')[0].getObject().aq_base is
... doc2.aq_base)
True
posted at: 13:07 |
0 comments |
category: /devel/zope
|
permanent link |
add to del.icio.us or digg it
I've just updated the HOWTO for using Testbrowser and Testrecorder with Plone. The Testbrowser/Testrecorder combination is so easy; also for non-programmers. We need more structured and well-documented functional tests like this, because they make our lives easier [*]. Maybe you can help out?
| [*] | ... and our tests slower? ;-) |
While I played around with Testrecorder, I wrote a small script for text match and replace using regular expressions. This is arguably one of the most unreadable pieces of code I've written in a while. But to the rescue come the doctests, which I've used to develop this test-first.
I don't know anything about Ron Jeffries but this is how he describes it and how it felt:
When you get this right, development turns into a very pleasant cycle of testing, seeing a simple thing to fix, fixing it, testing, getting positive feedback all the way. Guaranteed flow. And you go so fast! Try it, you'll like it.
Update: Martin incorporated the Testbrowser and Testrecorder HOWTO in his tutorial. I updated the link to point to that.
posted at: 01:10 |
0 comments |
category: /devel/zope
|
permanent link |
add to del.icio.us or digg it
Thanks to Hanno, ZopeSkel now has a template for starting Plone Core packages. Hanno is using ZopeSkel for the new plone.i18n package.
ZopeSkel has moved to the Collective. Get the latest and greatest of ZopeSkel via this command:
easy_install http://svn.plone.org/svn/collective/ZopeSkel/trunk#egg=ZopeSkel-dev
Remember from last time that Paste Script is useful for creating a consistent directory structure and files for you so that you can get to the actual work quickly. Plus, your projects will be ready for distribution without any additional work.
Now let's say we want to start a plone.form package. What we need to do is invoke paster create, telling it that we want to use the plone_core template. This is done using the -t command-line option. After invoking the command, we're asked for some variables:
$ paster create -t plone_core
Selected and implied templates:
ZopeSkel#plone_core A Plone Core project
Enter project name: plone.form
Variables:
package: ploneform
project: plone.form
Creating template plone_core
Enter namespace_package (Namespace package) ['plone']:
Enter package (The package contained namespace package (like i18n)) ['']: form
Enter version (Version) ['0.1']:
Enter description (One-line description of the package) ['']: Plone compatibility layer for zope.app.schema and zope.formlib
Enter long_description (Multi-line description (in reST)) ['']:
Enter author (Author name) ['Plone Foundation']:
Enter author_email (Author email) ['plone-developers@NOSPAMlists.sourceforge.net']:
Enter keywords (Space-separated keywords/tags) ['']:
Enter url (URL of homepage) ['']:
Enter license_name (License name) ['GPL']:
Enter zip_safe (True/False: if the package can be distributed as a .zip file) [False]:
Creating directory ./plone.form
Recursing into +namespace_package+
Creating ./plone.form/plone/
Recursing into +package+
Creating ./plone.form/plone/form/
Copying HISTORY.txt_tmpl to ./plone.form/plone/form/HISTORY.txt
Copying LICENSE.GPL to ./plone.form/plone/form/LICENSE.GPL
Copying LICENSE.txt_tmpl to ./plone.form/plone/form/LICENSE.txt
Copying README.txt_tmpl to ./plone.form/plone/form/README.txt
Copying __init__.py to ./plone.form/plone/form/__init__.py
Copying configure.zcml to ./plone.form/plone/form/configure.zcml
Copying version.txt_tmpl to ./plone.form/plone/form/version.txt
Copying __init__.py to ./plone.form/plone/__init__.py
Copying setup.cfg to ./plone.form/setup.cfg
Copying setup.py_tmpl to ./plone.form/setup.py
Running /usr/bin/python setup.py egg_info
Note that we typed in values for the project, package and descriptions variables only. For the rest we decided that the default was good enough. We're ready to start working on plone.form now.
There's no reason why we wouldn't use the plone_core template for our own packages. After all, the name of the namespace package and that of the contained package are variables, and the directory structure might well be useful for your own project.
Whenever the plone_core template changes, we can simply rerun the paster create command to update our project:
$ paster create -t plone_core
Selected and implied templates:
ZopeSkel#plone_core A Plone Core project
Enter project name: plone.form
Variables:
package: ploneform
project: plone.form
Creating template plone_core
Enter namespace_package (Namespace package) ['plone']:
Enter package (The package contained namespace package (like i18n)) ['']: form
[...]
Recursing into +namespace_package+
Recursing into +package+
./plone.form/plone/form/HISTORY.txt already exists (same content)
./plone.form/plone/form/LICENSE.GPL already exists (same content)
./plone.form/plone/form/LICENSE.txt already exists (same content)
./plone.form/plone/form/README.txt already exists (same content)
./plone.form/plone/form/__init__.py already exists (same content)
./plone.form/plone/form/configure.zcml already exists (same content)
./plone.form/plone/form/version.txt already exists (same content)
./plone.form/plone/__init__.py already exists (same content)
./plone.form/setup.cfg already exists (same content)
./plone.form/setup.py already exists (same content)
Running /usr/bin/python setup.py egg_info
If something had changed, we would have been presented a diff of our version of the file and the new version inside the template.
An inconvenience here is that when running paster create, we're asked for all variables again. Fortunately, there's the --config=CONFIG option that'll store all our variables in a file. Both for initial creation and for updating, our command becomes:
$ paster create -t plone_core --config=plone.form/template_vars.cfg
Extending the plone_core package to fit our own needs is really easy. Let's say we want to create a new template called my_package that's based on plone_core. We want our new template to use what's already there in plone_core and add a browser package in there with __init__.py and configure.zcml files.
Inside our SVN checkout of ZopeSkel, we create this directory:
$ mkdir -p zopeskel/templates/my_package/+namespace_package+/+package+/browser
Then we add our two files:
$ edit zopeskel/templates/my_package/+namespace_package+/+package+/browser/__init__.py_tmpl $ edit zopeskel/templates/my_package/+namespace_package+/+package+/browser/configure.zcml
Note that we create an __init__.py_tmpl file, with the _tmpl suffix because setuptools would currently not include our .py file in the distribution if the file ended with .py. So although our __init__.py_tmpl file isn't necessarily a template (nothing is substituted), we make it a Paste Script template so that it gets picked up by setuptools.
The next thing we do is wire up the my_package template so that it's available from the command-line. Inside zopeskel/__init__.py we add this:
class MyPackage(PloneCore):
_template_dir = 'templates/my_package'
summary = 'A Plone package that has a browser subpackage'
required_templates = ['plone_core']
Finally, we define an entry point for our template in setup.py:
[...] entry_points=""" [paste.paster_create_template] basic_zope = zopeskel:BasicZope plone_core = zopeskel:PloneCore my_package = zopeskel:MyPackage """, [...]
Note that we only added the my_package entry point here.
After calling setup.py develop we're ready to create a new project with our own template:
$ python setup.py develop [...] $ paster create --list-templates Available templates: basic_package: A basic setuptools-enabled package basic_zope: A Zope project my_package: A Plone package that has a browser subpackage paste_deploy: A web application deployed through paste.deploy plone_core: A Plone Core project
Easy as pie!
posted at: 15:30 |
3 comments |
category: /devel/zope
|
permanent link |
add to del.icio.us or digg it
| < | June 2006 | > | ||||
| Su | Mo | Tu | We | Th | Fr | Sa |
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | |
Feed of all categories:
rss |
atom