[Checkins] SVN: megrok.resource/tags/0.4.1/ Tagging version 0.4.1
Souheil CHELFOUH
souheil at chelfouh.com
Fri Feb 19 04:51:50 EST 2010
Log message for revision 109142:
Tagging version 0.4.1
Changed:
A megrok.resource/tags/0.4.1/
D megrok.resource/tags/0.4.1/docs/HISTORY.txt
A megrok.resource/tags/0.4.1/docs/HISTORY.txt
D megrok.resource/tags/0.4.1/setup.py
A megrok.resource/tags/0.4.1/setup.py
D megrok.resource/tags/0.4.1/src/megrok/resource/README.txt
A megrok.resource/tags/0.4.1/src/megrok/resource/README.txt
D megrok.resource/tags/0.4.1/src/megrok/resource/__init__.py
A megrok.resource/tags/0.4.1/src/megrok/resource/__init__.py
D megrok.resource/tags/0.4.1/src/megrok/resource/components.py
A megrok.resource/tags/0.4.1/src/megrok/resource/components.py
D megrok.resource/tags/0.4.1/src/megrok/resource/configure.zcml
A megrok.resource/tags/0.4.1/src/megrok/resource/configure.zcml
D megrok.resource/tags/0.4.1/src/megrok/resource/directives.py
A megrok.resource/tags/0.4.1/src/megrok/resource/directives.py
D megrok.resource/tags/0.4.1/src/megrok/resource/ftests/ftesting.zcml
A megrok.resource/tags/0.4.1/src/megrok/resource/ftests/ftesting.zcml
D megrok.resource/tags/0.4.1/src/megrok/resource/interfaces.py
A megrok.resource/tags/0.4.1/src/megrok/resource/interfaces.py
D megrok.resource/tags/0.4.1/src/megrok/resource/meta.py
A megrok.resource/tags/0.4.1/src/megrok/resource/meta.py
D megrok.resource/tags/0.4.1/src/megrok/resource/traversal.py
A megrok.resource/tags/0.4.1/src/megrok/resource/url.py
D megrok.resource/tags/0.4.1/src/megrok/resource/utils.py
A megrok.resource/tags/0.4.1/src/megrok/resource/utils.py
-=-
Deleted: megrok.resource/tags/0.4.1/docs/HISTORY.txt
===================================================================
--- megrok.resource/trunk/docs/HISTORY.txt 2010-02-18 01:40:27 UTC (rev 109103)
+++ megrok.resource/tags/0.4.1/docs/HISTORY.txt 2010-02-19 09:51:50 UTC (rev 109142)
@@ -1,30 +0,0 @@
-Changelog
-=========
-
-0.3 (2009-12-23)
-----------------
-
-* The IResourcesIncluder interface is now automatically implemented
- by the class while using the `include` directive. This makes the
- whole system a lot more natural.
-
-* The interfaces have been moved to a dedicated module. If you used
- to import from `components`, please, correct your code.
-
-0.2 (2009-12-22)
-----------------
-
-* Added a ResourceLibrary component that is a mix between a Library
- and a GroupInclusion. It allows to declare both the Library and the
- Resources in a single class but impacts the re-usability.
-
-* Library now directly inherits from grokcore.view.DirectoryResource,
- to inherit the `get` method behavior. This inheritance was avoided
- to prevent grokkers clash (grokcore.view.DirectoryResource grokker
- doesn't have a fallback for the `name` directive.). Our grokker has
- now the priority and explicitly set the `name` directive value.
-
-0.1 (2009-12-21)
-----------------
-
-* Initial release
Copied: megrok.resource/tags/0.4.1/docs/HISTORY.txt (from rev 109141, megrok.resource/trunk/docs/HISTORY.txt)
===================================================================
--- megrok.resource/tags/0.4.1/docs/HISTORY.txt (rev 0)
+++ megrok.resource/tags/0.4.1/docs/HISTORY.txt 2010-02-19 09:51:50 UTC (rev 109142)
@@ -0,0 +1,51 @@
+Changelog
+=========
+
+0.4.1 (2010-02-19)
+------------------
+
+* Fixed the case where a ResourceLibrary is included using the
+ "include" directive, in the same package. It was triggering an error
+ because a non-grokked ResourceLibrary does not provide
+ `IInclusion`. The directive now checks the subclass of the value to
+ determine if the given inclusion is a valid `IInclusion` or a
+ ResourceLibrary sub-class.
+
+0.4 (2010-02-18)
+----------------
+
+* Cleaned the dependencies : everything is declared as it
+ should. `zope.site` is now a main and not test dependency.
+
+* Renamed module "traversal" to "url", to describe accurately what the
+ module is about : url computation.
+
+* "mode" from `hurry.resource` is now exposed by the package.
+
+0.3 (2009-12-23)
+----------------
+
+* The IResourcesIncluder interface is now automatically implemented
+ by the class while using the `include` directive. This makes the
+ whole system a lot more natural.
+
+* The interfaces have been moved to a dedicated module. If you used
+ to import from `components`, please, correct your code.
+
+0.2 (2009-12-22)
+----------------
+
+* Added a ResourceLibrary component that is a mix between a Library
+ and a GroupInclusion. It allows to declare both the Library and the
+ Resources in a single class but impacts the re-usability.
+
+* Library now directly inherits from grokcore.view.DirectoryResource,
+ to inherit the `get` method behavior. This inheritance was avoided
+ to prevent grokkers clash (grokcore.view.DirectoryResource grokker
+ doesn't have a fallback for the `name` directive.). Our grokker has
+ now the priority and explicitly set the `name` directive value.
+
+0.1 (2009-12-21)
+----------------
+
+* Initial release
Deleted: megrok.resource/tags/0.4.1/setup.py
===================================================================
--- megrok.resource/trunk/setup.py 2010-02-18 01:40:27 UTC (rev 109103)
+++ megrok.resource/tags/0.4.1/setup.py 2010-02-19 09:51:50 UTC (rev 109142)
@@ -1,51 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from setuptools import setup, find_packages
-from os.path import join
-
-version = '0.3'
-HISTORY = open(join("docs", "HISTORY.txt")).read()
-README = open(join("src", "megrok", "resource", "README.txt")).read()
-
-test_requires = [
- 'zope.app.testing',
- 'zope.app.zcmlfiles',
- 'zope.publisher',
- 'zope.site',
- ]
-
-setup(name='megrok.resource',
- version=version,
- description="Grok Resources based on hurry.resource",
- long_description="%s\n%s" % (README, HISTORY),
- keywords='Grok Resources',
- author='Souheil Chelfouh',
- author_email='trollfot at gmail.com',
- url='',
- license='ZPL 2.1',
- packages=find_packages('src'),
- package_dir = {'': 'src'},
- namespace_packages=['megrok'],
- include_package_data=True,
- zip_safe=False,
- install_requires=[
- 'martian',
- 'setuptools',
- 'grokcore.component',
- 'grokcore.view',
- 'hurry.resource >= 0.4.1',
- 'hurry.zoperesource',
- 'z3c.hashedresource',
- 'zope.app.publication',
- 'zope.component',
- 'zope.interface',
- 'zope.security',
- 'zope.traversing'
- ],
- extras_require={'test': test_requires},
- classifiers=[
- "Programming Language :: Python",
- "Topic :: Software Development :: Libraries :: Python Modules",
- "License :: OSI Approved :: Zope Public License",
- ],
- )
Copied: megrok.resource/tags/0.4.1/setup.py (from rev 109141, megrok.resource/trunk/setup.py)
===================================================================
--- megrok.resource/tags/0.4.1/setup.py (rev 0)
+++ megrok.resource/tags/0.4.1/setup.py 2010-02-19 09:51:50 UTC (rev 109142)
@@ -0,0 +1,54 @@
+# -*- coding: utf-8 -*-
+
+from setuptools import setup, find_packages
+from os.path import join
+
+version = '0.4.1'
+HISTORY = open(join("docs", "HISTORY.txt")).read()
+README = open(join("src", "megrok", "resource", "README.txt")).read()
+
+test_requires = [
+ 'zope.app.testing',
+ 'zope.app.zcmlfiles',
+ 'zope.publisher',
+ 'zope.securitypolicy',
+ 'zope.testbrowser',
+ 'zope.testing',
+ ]
+
+setup(name='megrok.resource',
+ version=version,
+ description="Grok Resources based on hurry.resource",
+ long_description="%s\n%s" % (README, HISTORY),
+ keywords='Grok Resources',
+ author='Souheil Chelfouh',
+ author_email='trollfot at gmail.com',
+ url='',
+ license='ZPL 2.1',
+ packages=find_packages('src'),
+ package_dir = {'': 'src'},
+ namespace_packages=['megrok'],
+ include_package_data=True,
+ zip_safe=False,
+ install_requires=[
+ 'martian',
+ 'setuptools',
+ 'grokcore.component',
+ 'grokcore.view',
+ 'hurry.resource >= 0.4.1',
+ 'hurry.zoperesource',
+ 'z3c.hashedresource',
+ 'zope.site',
+ 'zope.app.publication',
+ 'zope.component',
+ 'zope.interface',
+ 'zope.security',
+ 'zope.traversing'
+ ],
+ extras_require={'test': test_requires},
+ classifiers=[
+ "Programming Language :: Python",
+ "Topic :: Software Development :: Libraries :: Python Modules",
+ "License :: OSI Approved :: Zope Public License",
+ ],
+ )
Deleted: megrok.resource/tags/0.4.1/src/megrok/resource/README.txt
===================================================================
--- megrok.resource/trunk/src/megrok/resource/README.txt 2010-02-18 01:40:27 UTC (rev 109103)
+++ megrok.resource/tags/0.4.1/src/megrok/resource/README.txt 2010-02-19 09:51:50 UTC (rev 109142)
@@ -1,287 +0,0 @@
-===============
-megrok.resource
-===============
-
-`megrok.resource` is a package destined to integrate `hurry.resource`
-and `z3c.hashedresource` into Grok applications.
-
-Setup
-=====
-
-Let's import and init the necessary work environment::
-
- >>> import grokcore.component as grok
- >>> from zope.testbrowser.testing import Browser
-
- >>> browser = Browser()
- >>> browser.handleErrors = False
-
-
-Library
-=======
-
-A Library is a component meant to expose a folder containing
-resources::
-
- >>> from megrok import resource
-
- >>> class SomeCSS(resource.Library):
- ... resource.path('ftests/css')
-
- >>> grok.testing.grok_component('somecss', SomeCSS)
- True
-
-Once grokked, the library provides the ILibrary interface and gets an
-accessible name::
-
- >>> from megrok.resource import ILibrary
- >>> ILibrary.providedBy(SomeCSS)
- True
-
- >>> SomeCSS.name
- 'somecss'
-
-At this point, it should be accessible via the component architecture
-as a named adapter::
-
- >>> from zope.component import getAdapter
- >>> from zope.publisher.browser import TestRequest
- >>> library = getAdapter(TestRequest(), name='somecss')
- >>> library
- <grokcore.view.components.DirectoryResource object at ...>
-
-
-Resources
-=========
-
-Simple resources
-----------------
-
-Resources can be declared as part of their library, with their
-dependencies::
-
- >>> css_a = resource.ResourceInclusion(SomeCSS, 'a.css')
- >>> css_b = resource.ResourceInclusion(SomeCSS, 'b.css')
-
-Grouping resources
-------------------
-
-Sometimes, resources need to be grouped logically. They can be
-declared in a group inclusion::
-
- >>> css_group = resource.GroupInclusion([css_a, css_b])
- >>> css_group.inclusions()
- [<ResourceInclusion 'a.css' in library 'somecss'>,
- <ResourceInclusion 'b.css' in library 'somecss'>]
-
-Library resource
-----------------
-
-Sometimes, it can be too cumbersome to declare the resources and the
-library separatly. When the resource is not destined to be re-used, it
-can be tempting to register everything with a single declaration. The
-ResourceLibrary component is what you need in these situations.
-
-A Resource library is a mix between a library and a group
-inclusion. You need to define the usual path and name and then, the
-linked resources::
-
- >>> class EasyResources(resource.ResourceLibrary):
- ... resource.path('ftests/css')
- ... resource.resource('a.css')
- ... resource.resource('b.css')
-
- >>> grok.testing.grok_component('someresources', EasyResources)
- True
-
-Once the component has been grokked, the resources are available::
-
- >>> EasyResources.inclusions()
- [<ResourceInclusion 'a.css' in library 'easyresources'>,
- <ResourceInclusion 'b.css' in library 'easyresources'>]
-
-
-Including resources in components
-=================================
-
-When rendering a web page we want to be able to include the resources
-where we need them.
-
-There are several ways to include them. It can be done automatically
-upon traversal on any IResourcesIncluder component, or manually specified.
-
-
-Traversal inclusion
--------------------
-
-For this example, we'll create a view and use the automatic inclusion,
-using the `include` directive::
-
- >>> from grokcore import view
- >>> from zope.interface import Interface
-
- >>> class MyView(view.View):
- ... grok.context(Interface)
- ... resource.include(css_a)
- ...
- ... def render(self): return ""
-
-For the resources to be automatically included during the traversal,
-we need to inform the publishing machinery that our component (the
-view), is a IResourcesIncluder. This is done automatically, when using
-the "include" directive::
-
- >>> resource.IResourcesIncluder.implementedBy(MyView)
- True
-
-Of course, this should not remove the existing interfaces
-implementations::
-
- >>> from zope.interface import Interface
- >>> class IMySuperIface(Interface): pass
-
- >>> class MyView(view.View):
- ... grok.context(Interface)
- ... grok.implements(IMySuperIface)
- ... resource.include(css_a)
- ...
- ... def render(self): return "<html><head></head></html>"
-
- >>> resource.IResourcesIncluder.implementedBy(MyView)
- True
- >>> IMySuperIface.implementedBy(MyView)
- True
-
-The `include` directive can be stacked, if several resources are to be
-included::
-
- >>> class AnotherView(MyView):
- ... resource.include(css_a)
- ... resource.include(css_b)
-
- >>> grok.testing.grok_component('AnotherView', AnotherView)
- True
-
- >>> browser.open('http://localhost/@@anotherview')
- >>> print browser.contents
- <html><head>
- <link... href="http://localhost/@@/++noop++.../somecss/a.css" />
- <link... href="http://localhost/@@/++noop++.../somecss/b.css" />
- </head></html>
-
-A ResourceLibrary component can be included just like a normal resource::
-
- >>> class YetAnotherView(view.View):
- ... grok.context(Interface)
- ... resource.include(EasyResources)
- ...
- ... def render(self):
- ... return u"<html><head></head></html>"
-
- >>> grok.testing.grok_component('yav', YetAnotherView)
- True
-
- >>> browser.open('http://localhost/@@yetanotherview')
- >>> print browser.contents
- <html><head>
- <link... href="http://localhost/@@/++noop++.../easyresources/a.css" />
- <link... href="http://localhost/@@/++noop++.../easyresources/b.css" />
- </head></html>
-
-
-Include validation
-------------------
-
-The `include` directive will raise an error if the provided value is
-not a valid inclusion object::
-
- >>> sneaky = object()
-
- >>> class FailingView(view.View):
- ... grok.context(Interface)
- ... resource.include(sneaky)
- ...
- ... def render(self):
- ... return u""
- Traceback (most recent call last):
- ...
- ValueError: You can only include IInclusions components.
-
-
-Remote inclusion
------------------
-
-Until now, we've seen that the resource inclusion could be made using
-the `include` directive. However, it can be very useful to be able to
-set inclusion on classes we don't "own". This "remote" inclusion is
-done using the `component_includes` function.
-
-We first register a view that includes no resources::
-
- >>> class DummyView(view.View):
- ... grok.context(Interface)
- ...
- ... def render(self):
- ... return u"<html><head></head></html>"
-
- >>> grok.testing.grok_component('dummy', DummyView)
- True
-
-The view class doesn't implement the needed interface::
-
- >>> resource.IResourcesIncluder.implementedBy(DummyView)
- False
-
-Now, we can use the remote inclusion function, to enable resources::
-
- >>> resource.component_includes(DummyView, css_group)
- >>> resource.IResourcesIncluder.implementedBy(DummyView)
- True
- >>> resource.include.bind().get(DummyView)
- [<hurry.resource.core.GroupInclusion object at ...>]
-
-This function can be used either on a class or an instance::
-
- >>> class UselessView(view.View):
- ... grok.context(Interface)
- ...
- ... def render(self): return u""
-
- >>> grok.testing.grok_component('useless', UselessView)
- True
-
- >>> from zope.component import getMultiAdapter
- >>> useless = getMultiAdapter(
- ... (object(), TestRequest()), name="uselessview")
- >>> useless
- <megrok.resource.ftests.UselessView object at ...>
-
- >>> resource.component_includes(useless, css_group)
- >>> resource.IResourcesIncluder.providedBy(useless)
- True
- >>> resource.include.bind().get(useless)
- (<hurry.resource.core.GroupInclusion object at ...>,)
-
-
-Cache and hash
-==============
-
-You probably noticed the "++noop++" traverser, in the resource
-URL. This is used to provide a hash and therefore, a unique URL. It
-can be very useful to work with caches and avoid outdated resources to
-be served.
-
-However, it can happen that this behavior (by default) is unwanted. To
-disable the use of the hashed URL, we can use the `use_hash` directive
-and set its value to False. This can be done either in the class
-definition or by using the directive `set` method::
-
- >>> from megrok.resource import use_hash
- >>> use_hash.set(SomeCSS, False)
-
- >>> browser.open('http://localhost/@@anotherview')
- >>> print browser.contents
- <html><head>
- <link... href="http://localhost/@@/somecss/a.css" />
- <link... href="http://localhost/@@/somecss/b.css" />
- </head></html>
Copied: megrok.resource/tags/0.4.1/src/megrok/resource/README.txt (from rev 109140, megrok.resource/trunk/src/megrok/resource/README.txt)
===================================================================
--- megrok.resource/tags/0.4.1/src/megrok/resource/README.txt (rev 0)
+++ megrok.resource/tags/0.4.1/src/megrok/resource/README.txt 2010-02-19 09:51:50 UTC (rev 109142)
@@ -0,0 +1,300 @@
+===============
+megrok.resource
+===============
+
+`megrok.resource` is a package destined to integrate `hurry.resource`
+and `z3c.hashedresource` into Grok applications.
+
+Setup
+=====
+
+Let's import and init the necessary work environment::
+
+ >>> import grokcore.component as grok
+ >>> from zope.testbrowser.testing import Browser
+
+ >>> browser = Browser()
+ >>> browser.handleErrors = False
+
+
+Library
+=======
+
+A Library is a component meant to expose a folder containing
+resources::
+
+ >>> from megrok import resource
+
+ >>> class SomeCSS(resource.Library):
+ ... resource.path('ftests/css')
+
+ >>> grok.testing.grok_component('somecss', SomeCSS)
+ True
+
+Once grokked, the library provides the ILibrary interface and gets an
+accessible name::
+
+ >>> from megrok.resource import ILibrary
+ >>> ILibrary.providedBy(SomeCSS)
+ True
+
+ >>> SomeCSS.name
+ 'somecss'
+
+At this point, it should be accessible via the component architecture
+as a named adapter::
+
+ >>> from zope.component import getAdapter
+ >>> from zope.publisher.browser import TestRequest
+ >>> library = getAdapter(TestRequest(), name='somecss')
+ >>> library
+ <grokcore.view.components.DirectoryResource object at ...>
+
+
+Resources
+=========
+
+Simple resources
+----------------
+
+Resources can be declared as part of their library, with their
+dependencies::
+
+ >>> css_a = resource.ResourceInclusion(SomeCSS, 'a.css')
+ >>> css_b = resource.ResourceInclusion(SomeCSS, 'b.css')
+
+Grouping resources
+------------------
+
+Sometimes, resources need to be grouped logically. They can be
+declared in a group inclusion::
+
+ >>> css_group = resource.GroupInclusion([css_a, css_b])
+ >>> css_group.inclusions()
+ [<ResourceInclusion 'a.css' in library 'somecss'>,
+ <ResourceInclusion 'b.css' in library 'somecss'>]
+
+Library resource
+----------------
+
+Sometimes, it can be too cumbersome to declare the resources and the
+library separatly. When the resource is not destined to be re-used, it
+can be tempting to register everything with a single declaration. The
+ResourceLibrary component is what you need in these situations.
+
+A Resource library is a mix between a library and a group
+inclusion. You need to define the usual path and name and then, the
+linked resources::
+
+ >>> class EasyResources(resource.ResourceLibrary):
+ ... resource.path('ftests/css')
+ ... resource.resource('a.css')
+ ... resource.resource('b.css')
+
+ >>> grok.testing.grok_component('someresources', EasyResources)
+ True
+
+Once the component has been grokked, the resources are available::
+
+ >>> EasyResources.inclusions()
+ [<ResourceInclusion 'a.css' in library 'easyresources'>,
+ <ResourceInclusion 'b.css' in library 'easyresources'>]
+
+
+Including resources in components
+=================================
+
+When rendering a web page we want to be able to include the resources
+where we need them.
+
+There are several ways to include them. It can be done automatically
+upon traversal on any IResourcesIncluder component, or manually specified.
+
+
+Traversal inclusion
+-------------------
+
+For this example, we'll create a view and use the automatic inclusion,
+using the `include` directive::
+
+ >>> from grokcore import view
+ >>> from zope.interface import Interface
+
+ >>> class MyView(view.View):
+ ... grok.context(Interface)
+ ... resource.include(css_a)
+ ...
+ ... def render(self): return ""
+
+For the resources to be automatically included during the traversal,
+we need to inform the publishing machinery that our component (the
+view), is a IResourcesIncluder. This is done automatically, when using
+the "include" directive::
+
+ >>> resource.IResourcesIncluder.implementedBy(MyView)
+ True
+
+Of course, this should not remove the existing interfaces
+implementations::
+
+ >>> from zope.interface import Interface
+ >>> class IMySuperIface(Interface): pass
+
+ >>> class MyView(view.View):
+ ... grok.context(Interface)
+ ... grok.implements(IMySuperIface)
+ ... resource.include(css_a)
+ ...
+ ... def render(self): return "<html><head></head></html>"
+
+ >>> resource.IResourcesIncluder.implementedBy(MyView)
+ True
+ >>> IMySuperIface.implementedBy(MyView)
+ True
+
+The `include` directive can be stacked, if several resources are to be
+included::
+
+ >>> class AnotherView(MyView):
+ ... resource.include(css_a)
+ ... resource.include(css_b)
+
+ >>> grok.testing.grok_component('AnotherView', AnotherView)
+ True
+
+ >>> browser.open('http://localhost/@@anotherview')
+ >>> print browser.contents
+ <html><head>
+ <link... href="http://localhost/@@/++noop++.../somecss/a.css" />
+ <link... href="http://localhost/@@/++noop++.../somecss/b.css" />
+ </head></html>
+
+A ResourceLibrary component can be included just like a normal resource::
+
+ >>> class YetAnotherView(view.View):
+ ... grok.context(Interface)
+ ... resource.include(EasyResources)
+ ...
+ ... def render(self):
+ ... return u"<html><head></head></html>"
+
+ >>> grok.testing.grok_component('yav', YetAnotherView)
+ True
+
+ >>> browser.open('http://localhost/@@yetanotherview')
+ >>> print browser.contents
+ <html><head>
+ <link... href="http://localhost/@@/++noop++.../easyresources/a.css" />
+ <link... href="http://localhost/@@/++noop++.../easyresources/b.css" />
+ </head></html>
+
+
+Include validation
+------------------
+
+The `include` directive will raise an error if the provided value is
+not a valid inclusion object::
+
+ >>> sneaky = object()
+
+ >>> class FailingView(view.View):
+ ... grok.context(Interface)
+ ... resource.include(sneaky)
+ ...
+ ... def render(self):
+ ... return u""
+ Traceback (most recent call last):
+ ...
+ ValueError: You can only include IInclusion or ResourceLibrary components.
+
+It should accept non-grokked ResourceLibraries as valid inclusions::
+
+ >>> class OtherResources(resource.ResourceLibrary):
+ ... resource.path('ftests/css')
+ ... resource.resource('a.css')
+
+ >>> class TolerantView(view.View):
+ ... grok.context(Interface)
+ ... resource.include(OtherResources)
+ ...
+ ... def render(self):
+ ... return u""
+
+
+Remote inclusion
+-----------------
+
+Until now, we've seen that the resource inclusion could be made using
+the `include` directive. However, it can be very useful to be able to
+set inclusion on classes we don't "own". This "remote" inclusion is
+done using the `component_includes` function.
+
+We first register a view that includes no resources::
+
+ >>> class DummyView(view.View):
+ ... grok.context(Interface)
+ ...
+ ... def render(self):
+ ... return u"<html><head></head></html>"
+
+ >>> grok.testing.grok_component('dummy', DummyView)
+ True
+
+The view class doesn't implement the needed interface::
+
+ >>> resource.IResourcesIncluder.implementedBy(DummyView)
+ False
+
+Now, we can use the remote inclusion function, to enable resources::
+
+ >>> resource.component_includes(DummyView, css_group)
+ >>> resource.IResourcesIncluder.implementedBy(DummyView)
+ True
+ >>> resource.include.bind().get(DummyView)
+ [<hurry.resource.core.GroupInclusion object at ...>]
+
+This function can be used either on a class or an instance::
+
+ >>> class UselessView(view.View):
+ ... grok.context(Interface)
+ ...
+ ... def render(self): return u""
+
+ >>> grok.testing.grok_component('useless', UselessView)
+ True
+
+ >>> from zope.component import getMultiAdapter
+ >>> useless = getMultiAdapter(
+ ... (object(), TestRequest()), name="uselessview")
+ >>> useless
+ <megrok.resource.ftests.UselessView object at ...>
+
+ >>> resource.component_includes(useless, css_group)
+ >>> resource.IResourcesIncluder.providedBy(useless)
+ True
+ >>> resource.include.bind().get(useless)
+ (<hurry.resource.core.GroupInclusion object at ...>,)
+
+
+Cache and hash
+==============
+
+You probably noticed the "++noop++" traverser, in the resource
+URL. This is used to provide a hash and therefore, a unique URL. It
+can be very useful to work with caches and avoid outdated resources to
+be served.
+
+However, it can happen that this behavior (by default) is unwanted. To
+disable the use of the hashed URL, we can use the `use_hash` directive
+and set its value to False. This can be done either in the class
+definition or by using the directive `set` method::
+
+ >>> from megrok.resource import use_hash
+ >>> use_hash.set(SomeCSS, False)
+
+ >>> browser.open('http://localhost/@@anotherview')
+ >>> print browser.contents
+ <html><head>
+ <link... href="http://localhost/@@/somecss/a.css" />
+ <link... href="http://localhost/@@/somecss/b.css" />
+ </head></html>
Deleted: megrok.resource/tags/0.4.1/src/megrok/resource/__init__.py
===================================================================
--- megrok.resource/trunk/src/megrok/resource/__init__.py 2010-02-18 01:40:27 UTC (rev 109103)
+++ megrok.resource/tags/0.4.1/src/megrok/resource/__init__.py 2010-02-19 09:51:50 UTC (rev 109142)
@@ -1,8 +0,0 @@
-from grokcore.view import path
-from grokcore.component import name
-from hurry.resource import ResourceInclusion, GroupInclusion
-
-from megrok.resource.directives import include, use_hash, resource
-from megrok.resource.components import Library, ResourceLibrary
-from megrok.resource.interfaces import IResourcesIncluder, ILibrary
-from megrok.resource.utils import component_includes
Copied: megrok.resource/tags/0.4.1/src/megrok/resource/__init__.py (from rev 109131, megrok.resource/trunk/src/megrok/resource/__init__.py)
===================================================================
--- megrok.resource/tags/0.4.1/src/megrok/resource/__init__.py (rev 0)
+++ megrok.resource/tags/0.4.1/src/megrok/resource/__init__.py 2010-02-19 09:51:50 UTC (rev 109142)
@@ -0,0 +1,8 @@
+from grokcore.view import path
+from grokcore.component import name
+from hurry.resource import ResourceInclusion, GroupInclusion, mode
+
+from megrok.resource.directives import include, use_hash, resource
+from megrok.resource.components import Library, ResourceLibrary
+from megrok.resource.interfaces import IResourcesIncluder, ILibrary
+from megrok.resource.utils import component_includes
Deleted: megrok.resource/tags/0.4.1/src/megrok/resource/components.py
===================================================================
--- megrok.resource/trunk/src/megrok/resource/components.py 2010-02-18 01:40:27 UTC (rev 109103)
+++ megrok.resource/tags/0.4.1/src/megrok/resource/components.py 2010-02-19 09:51:50 UTC (rev 109142)
@@ -1,40 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from grokcore.component import baseclass
-from grokcore.view import DirectoryResource
-from zope.component import getUtility
-from hurry.resource import ResourceInclusion, GroupInclusion
-from hurry.resource.interfaces import ICurrentNeededInclusions
-from megrok.resource.directives import resource
-from megrok.resource.interfaces import ILibrary
-
-
-class Library(DirectoryResource):
- """A library that exposes resources through an URL.
- This component is only used to declare a resources folder.
- """
- baseclass()
- name = None
-
-
-class ResourceLibrary(Library):
- """A library that behaves like a group inclusion.
- This prevents code redundance for simple libraries with
- few resources.
- """
- baseclass()
- depends = []
-
- @classmethod
- def need(cls):
- needed = getUtility(ICurrentNeededInclusions)()
- needed.need(cls)
-
- @classmethod
- def inclusions(cls):
- """Get all inclusions needed by this inclusion.
- """
- result = []
- for depend in cls.depends:
- result.extend(depend.inclusions())
- return result
Copied: megrok.resource/tags/0.4.1/src/megrok/resource/components.py (from rev 109131, megrok.resource/trunk/src/megrok/resource/components.py)
===================================================================
--- megrok.resource/tags/0.4.1/src/megrok/resource/components.py (rev 0)
+++ megrok.resource/tags/0.4.1/src/megrok/resource/components.py 2010-02-19 09:51:50 UTC (rev 109142)
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+
+from grokcore.component import baseclass
+from grokcore.view import DirectoryResource
+from zope.component import getUtility
+from hurry.resource.interfaces import ICurrentNeededInclusions
+
+
+class Library(DirectoryResource):
+ """A library that exposes resources through an URL.
+ This component is only used to declare a resources folder.
+ """
+ baseclass()
+ name = None
+
+
+class ResourceLibrary(Library):
+ """A library that behaves like a group inclusion.
+ This prevents code redundance for simple libraries with
+ few resources.
+ """
+ baseclass()
+ depends = []
+
+ @classmethod
+ def need(cls):
+ needed = getUtility(ICurrentNeededInclusions)()
+ needed.need(cls)
+
+ @classmethod
+ def inclusions(cls):
+ """Get all inclusions needed by this inclusion.
+ """
+ result = []
+ for depend in cls.depends:
+ result.extend(depend.inclusions())
+ return result
Deleted: megrok.resource/tags/0.4.1/src/megrok/resource/configure.zcml
===================================================================
--- megrok.resource/trunk/src/megrok/resource/configure.zcml 2010-02-18 01:40:27 UTC (rev 109103)
+++ megrok.resource/tags/0.4.1/src/megrok/resource/configure.zcml 2010-02-19 09:51:50 UTC (rev 109142)
@@ -1,15 +0,0 @@
-<configure
- xmlns="http://namespaces.zope.org/zope"
- xmlns:grok="http://namespaces.zope.org/grok"
- i18n_domain="zope">
-
- <include package="grokcore.component" file="meta.zcml" />
- <include package="grokcore.view" file="meta.zcml" />
- <include package="hurry.zoperesource" />
- <include package="z3c.hashedresource" />
-
- <grok:grok package=".event" />
- <grok:grok package=".traversal" />
- <grok:grok package=".meta" />
-
-</configure>
Copied: megrok.resource/tags/0.4.1/src/megrok/resource/configure.zcml (from rev 109131, megrok.resource/trunk/src/megrok/resource/configure.zcml)
===================================================================
--- megrok.resource/tags/0.4.1/src/megrok/resource/configure.zcml (rev 0)
+++ megrok.resource/tags/0.4.1/src/megrok/resource/configure.zcml 2010-02-19 09:51:50 UTC (rev 109142)
@@ -0,0 +1,15 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:grok="http://namespaces.zope.org/grok"
+ i18n_domain="zope">
+
+ <include package="grokcore.component" file="meta.zcml" />
+ <include package="grokcore.view" file="meta.zcml" />
+ <include package="hurry.zoperesource" />
+ <include package="z3c.hashedresource" />
+
+ <grok:grok package=".event" />
+ <grok:grok package=".url" />
+ <grok:grok package=".meta" />
+
+</configure>
Deleted: megrok.resource/tags/0.4.1/src/megrok/resource/directives.py
===================================================================
--- megrok.resource/trunk/src/megrok/resource/directives.py 2010-02-18 01:40:27 UTC (rev 109103)
+++ megrok.resource/tags/0.4.1/src/megrok/resource/directives.py 2010-02-19 09:51:50 UTC (rev 109142)
@@ -1,48 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import martian
-from hurry.resource import ResourceInclusion
-from hurry.resource.interfaces import IInclusion
-from megrok.resource.interfaces import IResourcesIncluder
-from zope.interface import classImplements
-from zope.interface.declarations import addClassAdvisor, _implements_advice
-
-
-def validateInclusion(directive, value):
- if not IInclusion.providedBy(value):
- raise ValueError(
- "You can only include IInclusions components.")
-
-
-class use_hash(martian.Directive):
- scope = martian.CLASS_OR_MODULE
- store = martian.ONCE
- default = True
-
- def factory(self, value):
- return bool(value)
-
-
-class include(martian.Directive):
- scope = martian.CLASS
- store = martian.MULTIPLE
- validate = validateInclusion
-
- def factory(self, resource):
- addClassAdvisor(_resources_advice, depth=3)
- return resource
-
-
-def _resources_advice(cls):
- if include.bind().get(cls):
- if not IResourcesIncluder.implementedBy(cls):
- classImplements(cls, IResourcesIncluder)
- return cls
-
-
-class resource(martian.Directive):
- scope = martian.CLASS
- store = martian.MULTIPLE
-
- def factory(self, relpath, depends=None, bottom=False):
- return (relpath, depends, bottom)
Copied: megrok.resource/tags/0.4.1/src/megrok/resource/directives.py (from rev 109140, megrok.resource/trunk/src/megrok/resource/directives.py)
===================================================================
--- megrok.resource/tags/0.4.1/src/megrok/resource/directives.py (rev 0)
+++ megrok.resource/tags/0.4.1/src/megrok/resource/directives.py 2010-02-19 09:51:50 UTC (rev 109142)
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+
+import martian
+from hurry.resource import ResourceInclusion
+from hurry.resource.interfaces import IInclusion
+from megrok.resource.components import ResourceLibrary
+from megrok.resource.interfaces import IResourcesIncluder
+from zope.interface import classImplements
+from zope.interface.declarations import addClassAdvisor
+
+
+def validateInclusion(directive, value):
+ if (not IInclusion.providedBy(value) and
+ not martian.util.check_subclass(value, ResourceLibrary)):
+ raise ValueError(
+ "You can only include IInclusion or"
+ " ResourceLibrary components.")
+
+
+class use_hash(martian.Directive):
+ scope = martian.CLASS_OR_MODULE
+ store = martian.ONCE
+ default = True
+
+ def factory(self, value):
+ return bool(value)
+
+
+class include(martian.Directive):
+ scope = martian.CLASS
+ store = martian.MULTIPLE
+ validate = validateInclusion
+
+ def factory(self, resource):
+ addClassAdvisor(_resources_advice, depth=3)
+ return resource
+
+
+def _resources_advice(cls):
+ if include.bind().get(cls):
+ if not IResourcesIncluder.implementedBy(cls):
+ classImplements(cls, IResourcesIncluder)
+ return cls
+
+
+class resource(martian.Directive):
+ scope = martian.CLASS
+ store = martian.MULTIPLE
+
+ def factory(self, relpath, depends=None, bottom=False):
+ return (relpath, depends, bottom)
Deleted: megrok.resource/tags/0.4.1/src/megrok/resource/ftests/ftesting.zcml
===================================================================
--- megrok.resource/trunk/src/megrok/resource/ftests/ftesting.zcml 2010-02-18 01:40:27 UTC (rev 109103)
+++ megrok.resource/tags/0.4.1/src/megrok/resource/ftests/ftesting.zcml 2010-02-19 09:51:50 UTC (rev 109142)
@@ -1,39 +0,0 @@
-<configure
- xmlns="http://namespaces.zope.org/zope"
- xmlns:grok="http://namespaces.zope.org/grok"
- i18n_domain="zope">
-
- <include package="grokcore.view" file="meta.zcml" />
- <include package="zope.app.zcmlfiles" file="meta.zcml" />
- <include package="zope.securitypolicy" file="meta.zcml" />
-
- <include package="zope.app.zcmlfiles" />
- <include package="zope.app.authentication" />
- <include package="grokcore.view" />
- <include package="megrok.resource" />
-
- <securityPolicy
- component="zope.securitypolicy.zopepolicy.ZopeSecurityPolicy"
- />
-
- <unauthenticatedPrincipal
- id="zope.anybody"
- title="Unauthenticated User"
- />
- <grant
- permission="zope.View"
- principal="zope.anybody"
- />
-
- <principal
- id="zope.mgr"
- title="Manager"
- login="mgr"
- password="mgrpw"
- />
-
- <role id="zope.Manager" title="Site Manager" />
- <grantAll role="zope.Manager" />
- <grant role="zope.Manager" principal="zope.mgr" />
-
-</configure>
Copied: megrok.resource/tags/0.4.1/src/megrok/resource/ftests/ftesting.zcml (from rev 109131, megrok.resource/trunk/src/megrok/resource/ftests/ftesting.zcml)
===================================================================
--- megrok.resource/tags/0.4.1/src/megrok/resource/ftests/ftesting.zcml (rev 0)
+++ megrok.resource/tags/0.4.1/src/megrok/resource/ftests/ftesting.zcml 2010-02-19 09:51:50 UTC (rev 109142)
@@ -0,0 +1,28 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:grok="http://namespaces.zope.org/grok"
+ i18n_domain="zope">
+
+ <include package="grokcore.view" file="meta.zcml" />
+ <include package="zope.app.zcmlfiles" file="meta.zcml" />
+ <include package="zope.securitypolicy" file="meta.zcml" />
+
+ <include package="zope.app.zcmlfiles" />
+ <include package="grokcore.view" />
+ <include package="megrok.resource" />
+
+ <securityPolicy
+ component="zope.securitypolicy.zopepolicy.ZopeSecurityPolicy"
+ />
+
+ <unauthenticatedPrincipal
+ id="zope.anybody"
+ title="Unauthenticated User"
+ />
+
+ <grant
+ permission="zope.View"
+ principal="zope.anybody"
+ />
+
+</configure>
Deleted: megrok.resource/tags/0.4.1/src/megrok/resource/interfaces.py
===================================================================
--- megrok.resource/trunk/src/megrok/resource/interfaces.py 2010-02-18 01:40:27 UTC (rev 109103)
+++ megrok.resource/tags/0.4.1/src/megrok/resource/interfaces.py 2010-02-19 09:51:50 UTC (rev 109142)
@@ -1,12 +0,0 @@
-from zope.interface import Interface, Attribute
-
-
-class IResourcesIncluder(Interface):
- """A publishable component that can include resources.
- """
-
-class ILibrary(Interface):
- """A library, including resources.
- """
- name = Attribute("The name of the library needed for URL computations")
-
Copied: megrok.resource/tags/0.4.1/src/megrok/resource/interfaces.py (from rev 109131, megrok.resource/trunk/src/megrok/resource/interfaces.py)
===================================================================
--- megrok.resource/tags/0.4.1/src/megrok/resource/interfaces.py (rev 0)
+++ megrok.resource/tags/0.4.1/src/megrok/resource/interfaces.py 2010-02-19 09:51:50 UTC (rev 109142)
@@ -0,0 +1,14 @@
+# -*- coding: utf-8 -*-
+
+from zope.interface import Interface, Attribute
+
+
+class IResourcesIncluder(Interface):
+ """A publishable component that can include resources.
+ """
+
+
+class ILibrary(Interface):
+ """A library, including resources.
+ """
+ name = Attribute("The name of the library needed for URL computations")
Deleted: megrok.resource/tags/0.4.1/src/megrok/resource/meta.py
===================================================================
--- megrok.resource/trunk/src/megrok/resource/meta.py 2010-02-18 01:40:27 UTC (rev 109103)
+++ megrok.resource/tags/0.4.1/src/megrok/resource/meta.py 2010-02-19 09:51:50 UTC (rev 109142)
@@ -1,54 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import martian
-from grokcore import component
-from grokcore import view
-
-from grokcore.view.meta.directoryresource import DirectoryResourceGrokker
-from hurry.resource import ResourceInclusion, NeededInclusions
-from hurry.resource.interfaces import IInclusion
-from megrok.resource import Library, ILibrary, ResourceLibrary
-from megrok.resource import resource
-from zope.interface import alsoProvides
-
-
-def default_library_name(factory, module=None, **data):
- return factory.__name__.lower()
-
-
-class LibraryGrokker(martian.ClassGrokker):
- martian.component(Library)
- martian.priority(500)
- martian.directive(view.path)
- martian.directive(component.name, get_default=default_library_name)
-
- def execute(self, factory, config, name, path, **kw):
- # We set the name using the grok.name or the class name
- # We do that only if the attribute is not already set.
- if getattr(factory, 'name', None) is None:
- factory.name = name
-
- # We need to make sure the name is available for the Directory
- # Resource Grokker.
- if not component.name.bind().get(factory):
- component.name.set(factory, name)
-
- # We provide ILibrary. It is needed since classProvides
- # is not inherited.
- alsoProvides(factory, ILibrary)
- return True
-
-
-class ResourceLibraryGrokker(martian.ClassGrokker):
- martian.component(ResourceLibrary)
- martian.directive(resource, default=[])
-
- def create_resources(self, library, resources):
- for (filename, depends, bottom) in resources:
- yield ResourceInclusion(
- library, filename, depends=depends, bottom=bottom)
-
- def execute(self, factory, config, resource, **kw):
- factory.depends = list(self.create_resources(factory, resource))
- alsoProvides(factory, IInclusion)
- return True
Copied: megrok.resource/tags/0.4.1/src/megrok/resource/meta.py (from rev 109131, megrok.resource/trunk/src/megrok/resource/meta.py)
===================================================================
--- megrok.resource/tags/0.4.1/src/megrok/resource/meta.py (rev 0)
+++ megrok.resource/tags/0.4.1/src/megrok/resource/meta.py 2010-02-19 09:51:50 UTC (rev 109142)
@@ -0,0 +1,53 @@
+# -*- coding: utf-8 -*-
+
+import martian
+from grokcore import component
+from grokcore import view
+
+from hurry.resource import ResourceInclusion
+from hurry.resource.interfaces import IInclusion
+from megrok.resource import Library, ILibrary, ResourceLibrary
+from megrok.resource import resource
+from zope.interface import alsoProvides
+
+
+def default_library_name(factory, module=None, **data):
+ return factory.__name__.lower()
+
+
+class LibraryGrokker(martian.ClassGrokker):
+ martian.component(Library)
+ martian.priority(500)
+ martian.directive(view.path)
+ martian.directive(component.name, get_default=default_library_name)
+
+ def execute(self, factory, config, name, path, **kw):
+ # We set the name using the grok.name or the class name
+ # We do that only if the attribute is not already set.
+ if getattr(factory, 'name', None) is None:
+ factory.name = name
+
+ # We need to make sure the name is available for the Directory
+ # Resource Grokker.
+ if not component.name.bind().get(factory):
+ component.name.set(factory, name)
+
+ # We provide ILibrary. It is needed since classProvides
+ # is not inherited.
+ alsoProvides(factory, ILibrary)
+ return True
+
+
+class ResourceLibraryGrokker(martian.ClassGrokker):
+ martian.component(ResourceLibrary)
+ martian.directive(resource, default=[])
+
+ def create_resources(self, library, resources):
+ for (filename, depends, bottom) in resources:
+ yield ResourceInclusion(
+ library, filename, depends=depends, bottom=bottom)
+
+ def execute(self, factory, config, resource, **kw):
+ factory.depends = list(self.create_resources(factory, resource))
+ alsoProvides(factory, IInclusion)
+ return True
Deleted: megrok.resource/tags/0.4.1/src/megrok/resource/traversal.py
===================================================================
--- megrok.resource/trunk/src/megrok/resource/traversal.py 2010-02-18 01:40:27 UTC (rev 109103)
+++ megrok.resource/tags/0.4.1/src/megrok/resource/traversal.py 2010-02-19 09:51:50 UTC (rev 109142)
@@ -1,27 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import megrok.resource
-import grokcore.component as grok
-
-from zope.component import getAdapter
-from zope.site.hooks import getSite
-from zope.traversing.browser.absoluteurl import absoluteURL
-
-from hurry.resource.interfaces import ILibraryUrl
-from hurry.zoperesource.zopesupport import getRequest
-from z3c.hashedresource.interfaces import IResourceContentsHash
-
-
- at grok.implementer(ILibraryUrl)
- at grok.adapter(megrok.resource.ILibrary)
-def library_url(library):
- request = getRequest()
- use_hash = megrok.resource.use_hash.bind().get(library)
- base_url = absoluteURL(getSite(), request)
-
- if use_hash is True:
- resource = getAdapter(request, name=library.name)
- hashpath = IResourceContentsHash(resource)
- return '%s/@@/++noop++%s/%s' % (base_url, hashpath, library.name)
-
- return '%s/@@/%s' % (base_url, library.name)
Copied: megrok.resource/tags/0.4.1/src/megrok/resource/url.py (from rev 109131, megrok.resource/trunk/src/megrok/resource/url.py)
===================================================================
--- megrok.resource/tags/0.4.1/src/megrok/resource/url.py (rev 0)
+++ megrok.resource/tags/0.4.1/src/megrok/resource/url.py 2010-02-19 09:51:50 UTC (rev 109142)
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+
+import megrok.resource
+import grokcore.component as grok
+
+from zope.component import getAdapter
+from zope.site.hooks import getSite
+from zope.traversing.browser.absoluteurl import absoluteURL
+
+from hurry.resource.interfaces import ILibraryUrl
+from hurry.zoperesource.zopesupport import getRequest
+from z3c.hashedresource.interfaces import IResourceContentsHash
+
+
+ at grok.implementer(ILibraryUrl)
+ at grok.adapter(megrok.resource.ILibrary)
+def library_url(library):
+ request = getRequest()
+ use_hash = megrok.resource.use_hash.bind().get(library)
+ base_url = absoluteURL(getSite(), request)
+
+ if use_hash is True:
+ resource = getAdapter(request, name=library.name)
+ hashpath = IResourceContentsHash(resource)
+ return '%s/@@/++noop++%s/%s' % (base_url, hashpath, library.name)
+
+ return '%s/@@/%s' % (base_url, library.name)
Deleted: megrok.resource/tags/0.4.1/src/megrok/resource/utils.py
===================================================================
--- megrok.resource/trunk/src/megrok/resource/utils.py 2010-02-18 01:40:27 UTC (rev 109103)
+++ megrok.resource/tags/0.4.1/src/megrok/resource/utils.py 2010-02-19 09:51:50 UTC (rev 109142)
@@ -1,16 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-from martian.util import isclass
-from megrok.resource import include, IResourcesIncluder
-from zope.interface import classImplements, alsoProvides
-
-def component_includes(component, *resources):
- if isclass(component):
- if not IResourcesIncluder.implementedBy(component):
- classImplements(component, IResourcesIncluder)
- else:
- if not IResourcesIncluder.providedBy(component):
- alsoProvides(component, IResourcesIncluder)
-
- include.set(component, resources)
Copied: megrok.resource/tags/0.4.1/src/megrok/resource/utils.py (from rev 109131, megrok.resource/trunk/src/megrok/resource/utils.py)
===================================================================
--- megrok.resource/tags/0.4.1/src/megrok/resource/utils.py (rev 0)
+++ megrok.resource/tags/0.4.1/src/megrok/resource/utils.py 2010-02-19 09:51:50 UTC (rev 109142)
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from martian.util import isclass
+from megrok.resource import include, IResourcesIncluder
+from zope.interface import classImplements, alsoProvides
+
+
+def component_includes(component, *resources):
+ if isclass(component):
+ if not IResourcesIncluder.implementedBy(component):
+ classImplements(component, IResourcesIncluder)
+ else:
+ if not IResourcesIncluder.providedBy(component):
+ alsoProvides(component, IResourcesIncluder)
+
+ include.set(component, resources)
More information about the checkins
mailing list