|
/
Zope
/
gocept svn checkins
/
Archive
/
2008
/
2008-07
/
SVN: r6038 - gocept.cvs/tags/0.1.9
[
SVN: r6030 - CMFLinkChecker/branches/2.1 / ... ]
[
SVN: r6043 - in CMFLinkChecker/trunk: . ... ]
SVN: r6038 - gocept.cvs/tags/0.1.9
Michael Howitz <mh(at)gocept.com> |
2008-07-14 15:01:48 |
[ FULL ]
|
Author: mac
Date: Mon Jul 14 15:01:48 2008
New Revision: 6038
Log:
releasing 0.1.9
Added:
gocept.cvs/tags/0.1.9/
- copied from r6037, gocept.cvs/trunk/
|
SVN: r6039 - gocept.cvs/tags/0.1.9
Michael Howitz <mh(at)gocept.com> |
2008-07-14 15:03:11 |
[ FULL ]
|
Author: mac
Date: Mon Jul 14 15:03:10 2008
New Revision: 6039
Log:
removed dev
Modified:
gocept.cvs/tags/0.1.9/setup.py
Modified: gocept.cvs/tags/0.1.9/setup.py
==============================================================================
--- gocept.cvs/tags/0.1.9/setup.py (original)
+++ gocept.cvs/tags/0.1.9/setup.py Mon Jul 14 15:03:10 2008
(at)(at) -3,7 +3,7 (at)(at)
name = "gocept.cvs"
setup(
name = name,
- version = "0.1.9dev",
+ version = "0.1.9",
author = "Daniel Havlik",
author_email = "dh(at)gocept.com",
description = "zc.buildout recipe for checking out cvs modules.",
|
SVN: r6040 - gocept.cvs/trunk
Michael Howitz <mh(at)gocept.com> |
2008-07-14 15:06:12 |
[ FULL ]
|
Author: mac
Date: Mon Jul 14 15:06:11 2008
New Revision: 6040
Log:
0.1.9 is history
Modified:
gocept.cvs/trunk/setup.py
Modified: gocept.cvs/trunk/setup.py
==============================================================================
--- gocept.cvs/trunk/setup.py (original)
+++ gocept.cvs/trunk/setup.py Mon Jul 14 15:06:11 2008
(at)(at) -3,7 +3,7 (at)(at)
name = "gocept.cvs"
setup(
name = name,
- version = "0.1.9dev",
+ version = "0.1.10dev",
author = "Daniel Havlik",
author_email = "dh(at)gocept.com",
description = "zc.buildout recipe for checking out cvs modules.",
|
SVN: r6057 - gocept.cvs/tags/0.1.10
Michael Howitz <mh(at)gocept.com> |
2008-07-15 09:26:20 |
[ FULL ]
|
Author: mac
Date: Tue Jul 15 09:26:19 2008
New Revision: 6057
Log:
releasing 0.1.10
Added:
gocept.cvs/tags/0.1.10/
- copied from r6056, gocept.cvs/trunk/
|
SVN: r6058 - gocept.cvs/tags/0.1.10
Michael Howitz <mh(at)gocept.com> |
2008-07-15 09:27:41 |
[ FULL ]
|
Author: mac
Date: Tue Jul 15 09:27:40 2008
New Revision: 6058
Log:
removing dev
Modified:
gocept.cvs/tags/0.1.10/setup.py
Modified: gocept.cvs/tags/0.1.10/setup.py
==============================================================================
--- gocept.cvs/tags/0.1.10/setup.py (original)
+++ gocept.cvs/tags/0.1.10/setup.py Tue Jul 15 09:27:40 2008
(at)(at) -3,7 +3,7 (at)(at)
name = "gocept.cvs"
setup(
name = name,
- version = "0.1.10dev",
+ version = "0.1.10",
author = "Daniel Havlik",
author_email = "dh(at)gocept.com",
description = "zc.buildout recipe for checking out cvs modules.",
|
SVN: r6059 - gocept.cvs/trunk
Michael Howitz <mh(at)gocept.com> |
2008-07-15 09:28:31 |
[ FULL ]
|
Author: mac
Date: Tue Jul 15 09:28:30 2008
New Revision: 6059
Log:
0.1.10 is history
Modified:
gocept.cvs/trunk/setup.py
Modified: gocept.cvs/trunk/setup.py
==============================================================================
--- gocept.cvs/trunk/setup.py (original)
+++ gocept.cvs/trunk/setup.py Tue Jul 15 09:28:30 2008
(at)(at) -3,7 +3,7 (at)(at)
name = "gocept.cvs"
setup(
name = name,
- version = "0.1.10dev",
+ version = "0.1.11dev",
author = "Daniel Havlik",
author_email = "dh(at)gocept.com",
description = "zc.buildout recipe for checking out cvs modules.",
|
SVN: r6078 - gocept.lms/trunk/src/gocept/lms
Christian Zagrodnick <cz(at)gocept.com> |
2008-07-15 16:03:36 |
[ FULL ]
|
Author: zagy
Date: Tue Jul 15 16:03:35 2008
New Revision: 6078
Log:
documentation
Modified:
gocept.lms/trunk/src/gocept/lms/schedule.txt
Modified: gocept.lms/trunk/src/gocept/lms/schedule.txt
==============================================================================
--- gocept.lms/trunk/src/gocept/lms/schedule.txt (original)
+++ gocept.lms/trunk/src/gocept/lms/schedule.txt Tue Jul 15 16:03:35 2008
(at)(at) -2,28 +2,37 (at)(at)
The scheduler
=============
-[#functionaltest]_
+The scheduler looks over the URLs in the database and decides which one have
to
+be checked[#functionaltest]_.
+
+Register some URLs:
>>> import zope.component
>>> import gocept.lms.interfaces
-
>>> urls =
zope.component.getUtility(gocept.lms.interfaces.IURLProvider)
-
>>> url1 = urls.add('http://example.com/1')
>>> url2 = urls.add('http://example.com/2')
>>> url3 = urls.add('http://example.com/3')
>>> url4 = urls.add('http://example.com/4')
+Set different states:
+
>>> url1.state = gocept.lms.interfaces.STATE_OK
>>> url2.state = gocept.lms.interfaces.STATE_TEMPORARY
>>> url3.state = gocept.lms.interfaces.STATE_UNAVAILABLE
+The scheduler puts the URLs to be checked into the check queue. Initially it
is
+empty:
+
>>> import zc.queue.interfaces
>>> check_queue =
zope.component.getUtility(zc.queue.interfaces.IQueue,
... name='check')
>>> list(check_queue)
[]
+Run the scheduler. None of the created URLs have been checked so the queue
will
+contain all URLs after the scheduling run:
+
>>> import gocept.lms.schedule
>>> gocept.lms.schedule.schedule()
>>> list(check_queue)
(at)(at) -33,6 +42,8 (at)(at)
<gocept.lms.url.URL 'http://example.com/4'>]
+
+
.. [#functionaltest] Setup functional test
>>> import gocept.lms.app
|
SVN: r6080 - gocept.lms/trunk/src/gocept/lms
Christian Zagrodnick <cz(at)gocept.com> |
2008-07-15 16:51:43 |
[ FULL ]
|
Author: zagy
Date: Tue Jul 15 16:51:42 2008
New Revision: 6080
Log:
more tests
Modified:
gocept.lms/trunk/src/gocept/lms/schedule.txt
Modified: gocept.lms/trunk/src/gocept/lms/schedule.txt
==============================================================================
--- gocept.lms/trunk/src/gocept/lms/schedule.txt (original)
+++ gocept.lms/trunk/src/gocept/lms/schedule.txt Tue Jul 15 16:51:42 2008
(at)(at) -42,6 +42,110 (at)(at)
<gocept.lms.url.URL 'http://example.com/4'>]
+When we run the scheduler again we'll have every link twice in the queue:
+
+>>> gocept.lms.schedule.schedule()
+>>> list(check_queue)
+[<gocept.lms.url.URL 'http://example.com/1'>,
+ <gocept.lms.url.URL 'http://example.com/2'>,
+ <gocept.lms.url.URL 'http://example.com/3'>,
+ <gocept.lms.url.URL 'http://example.com/4'>,
+ <gocept.lms.url.URL 'http://example.com/1'>,
+ <gocept.lms.url.URL 'http://example.com/2'>,
+ <gocept.lms.url.URL 'http://example.com/3'>,
+ <gocept.lms.url.URL 'http://example.com/4'>]
+
+
+Let's empty the queue and set last_check dates:
+
+>>> while check_queue:
+... check_queue.pull()
+<gocept.lms.url.URL 'http://example.com/1'>
+<gocept.lms.url.URL 'http://example.com/2'>
+<gocept.lms.url.URL 'http://example.com/3'>
+<gocept.lms.url.URL 'http://example.com/4'>
+<gocept.lms.url.URL 'http://example.com/1'>
+<gocept.lms.url.URL 'http://example.com/2'>
+<gocept.lms.url.URL 'http://example.com/3'>
+<gocept.lms.url.URL 'http://example.com/4'>
+>>> list(check_queue)
+[]
+
+>>> import datetime
+>>> import pytz
+>>> now = datetime.datetime.now(pytz.UTC)
+>>> second = datetime.timedelta(seconds=1)
+>>> url1.last_check = now
+>>> url2.last_check = now + second
+>>> url3.last_check = now + 2*second
+>>> url4.last_check = now + 3*second
+
+Since we're using a catalog we need to send ObjectModified events:
+
+>>> import zope.event
+>>> import zope.lifecycleevent
+>>> zope.event.notify(zope.lifecycleevent.ObjectModifiedEvent(url1))
+>>> zope.event.notify(zope.lifecycleevent.ObjectModifiedEvent(url2))
+>>> zope.event.notify(zope.lifecycleevent.ObjectModifiedEvent(url3))
+>>> zope.event.notify(zope.lifecycleevent.ObjectModifiedEvent(url4))
+
+When we schedule now, nothing will be added to the check queue:
+
+>>> gocept.lms.schedule.schedule()
+>>> list(check_queue)
+[]
+
+Lower the check interval to one second:
+
+>>> gocept.lms.schedule.INTERVAL = datetime.timedelta(seconds=1)
+
+Let's wait a second and schedule again:
+
+>>> import time
+>>> time.sleep(1)
+>>> gocept.lms.schedule.schedule()
+>>> list(check_queue)
+[<gocept.lms.url.URL 'http://example.com/1'>]
+
+"check" the entire queue:
+
+>>> def check_all():
+... while check_queue:
+... url = check_queue.pull()
+... url.last_check = datetime.datetime.now(pytz.UTC)
+... zope.event.notify(zope.lifecycleevent.ObjectModifiedEvent(url))
+>>> check_all()
+
+When we schedule now, nothing will be put to the queue again:
+
+
+>>> gocept.lms.schedule.schedule()
+>>> list(check_queue)
+[]
+
+
+Let's wait a second and schedule again. Now 1 and 2 are to be checked:
+
+>>> import time
+>>> time.sleep(1)
+>>> gocept.lms.schedule.schedule()
+>>> list(check_queue)
+[<gocept.lms.url.URL 'http://example.com/1'>,
+ <gocept.lms.url.URL 'http://example.com/2'>]
+
+"check" the queue:
+
+>>> check_all()
+
+When we schedule now, nothing will be put to the queue again:
+
+>>> gocept.lms.schedule.schedule()
+>>> list(check_queue)
+[]
+
+
+
+
.. [#functionaltest] Setup functional test
|
SVN: r6083 - gocept.lms/trunk/src/gocept/lms
Christian Theune <ct(at)gocept.com> |
2008-07-15 18:15:30 |
[ FULL ]
|
Author: ctheune
Date: Tue Jul 15 18:15:29 2008
New Revision: 6083
Log:
codify edge case and why it is ok for us
Modified:
gocept.lms/trunk/src/gocept/lms/notify.txt
Modified: gocept.lms/trunk/src/gocept/lms/notify.txt
==============================================================================
--- gocept.lms/trunk/src/gocept/lms/notify.txt (original)
+++ gocept.lms/trunk/src/gocept/lms/notify.txt Tue Jul 15 18:15:29 2008
(at)(at) -52,20 +52,19 (at)(at)
Connect: None
Update many states: fred - 3
-# XXX solve this case
-#When Fred subscribes to another URL he will be notified about its state:
-#
-#>>> fred.register_urls([url4])
-#>>> notify()
-#>>> xmlrpc.show_log()
-#Connect: None
-#Update many states: fred - 1
-
Running another notification would not produce any actions, because Fred was
successfully notified:
>>> notify()
>>> xmlrpc.show_log()
+When Fred subscribes to another URL that has a `last state change` date
+befor his last notification he will not receive a notification from this
+component (those status updates are handled by the XML-RPC interface):
+
+>>> fred.register_urls([url4])
+>>> notify()
+>>> xmlrpc.show_log()
+
.. [#functionaltest] Setup functional test
>>> import gocept.lms.app
|
SVN: r6084 - gocept.lms/trunk/src/gocept/lms
Christian Theune <ct(at)gocept.com> |
2008-07-16 09:07:28 |
[ FULL ]
|
Author: ctheune
Date: Wed Jul 16 09:07:26 2008
New Revision: 6084
Log:
Make set-/getClientNotifications functional.
Modified:
gocept.lms/trunk/src/gocept/lms/app.py
gocept.lms/trunk/src/gocept/lms/xmlrpc.txt
Modified: gocept.lms/trunk/src/gocept/lms/app.py
==============================================================================
--- gocept.lms/trunk/src/gocept/lms/app.py (original)
+++ gocept.lms/trunk/src/gocept/lms/app.py Wed Jul 16 09:07:26 2008
(at)(at) -121,13 +121,13 (at)(at)
def checkConnection(self, client, password):
return PROTOCOL_VERSION
- def getClientNotifications(self, client_id, password):
- # XXX API stub
- return False
+ (at)authenticatedClient
+ def getClientNotifications(self, client, password):
+ return client.notify
- def setClientNotifications(self, client_id, password, status):
- # XXX API stub
- pass
+ (at)authenticatedClient
+ def setClientNotifications(self, client, password, status):
+ client.notify = bool(status)
(at)authenticatedClient
def registerURLs(self, client, password, urls):
Modified: gocept.lms/trunk/src/gocept/lms/xmlrpc.txt
==============================================================================
--- gocept.lms/trunk/src/gocept/lms/xmlrpc.txt (original)
+++ gocept.lms/trunk/src/gocept/lms/xmlrpc.txt Wed Jul 16 09:07:26 2008
(at)(at) -122,13 +122,33 (at)(at)
XXX what happens when invalid urls are registered?
+Setting/getting the notification status
+=======================================
-Various API methods, currently implemented as stubs
-===================================================
+Clients can choose whether or not hey want to retrieve notifications. This
+flag can be either set manually using the XML-RPC API or sometimes is set by
+the server (e.g. after a certain number of failed notifications):
+Initially, the notifications are sent:
+>>> server.getClientNotifications('gocept', password)
+True
+
+The client can choose to not receive them anymore:
+
+>>> server.setClientNotifications('gocept', password, False)
>>> server.getClientNotifications('gocept', password)
False
+
+And can re-enable them:
+
>>> server.setClientNotifications('gocept', password, True)
+>>> server.getClientNotifications('gocept', password)
+True
+
+
+Various API methods, currently implemented as stubs
+===================================================
+
>>> server.unregisterURLs('gocept', password, ['http://localhost'])
>>> server.getInfoFrameURL('gocept', password)
'http://localhost:8080/lms'
|
SVN: r6085 - gocept.lms/trunk/src/gocept/lms
Thomas Lotze <tl(at)gocept.com> |
2008-07-16 09:50:53 |
[ FULL ]
|
Author: thomas
Date: Wed Jul 16 09:50:52 2008
New Revision: 6085
Log:
ensure that a client isn't notified too frequently, added tests
Modified:
gocept.lms/trunk/src/gocept/lms/notify.py
gocept.lms/trunk/src/gocept/lms/notify.txt
Modified: gocept.lms/trunk/src/gocept/lms/notify.py
==============================================================================
--- gocept.lms/trunk/src/gocept/lms/notify.py (original)
+++ gocept.lms/trunk/src/gocept/lms/notify.py Wed Jul 16 09:50:52 2008
(at)(at) -14,6 +14,10 (at)(at)
import xmlrpclib
+
+INTERVAL = datetime.timedelta(seconds=5*60)
+
+
# Provide hook for tests to set up dummies
ServerProxy = xmlrpclib.ServerProxy
(at)(at) -21,12 +25,17 (at)(at)
def notify():
url_query = zope.component.getUtility(hurry.query.interfaces.IQuery)
+ reference_time = datetime.datetime.now(pytz.UTC) - INTERVAL
+
# Notify each client about URL changes that happened since the last
# notification.
clients = zope.component.getUtility(gocept.lms.interfaces.IClientProvider)
for client in clients.values():
if not client.notify:
continue
+ if client.last_notification > reference_time:
+ # don't notify clients more frequently than every 5 minutes
+ continue
urls = url_query.searchResults(
Ge(('urls', 'last_state_change'), client.last_notification) &
AnyOf(('urls', 'clients'), [client]))
Modified: gocept.lms/trunk/src/gocept/lms/notify.txt
==============================================================================
--- gocept.lms/trunk/src/gocept/lms/notify.txt (original)
+++ gocept.lms/trunk/src/gocept/lms/notify.txt Wed Jul 16 09:50:52 2008
(at)(at) -22,6 +22,12 (at)(at)
... self.log = []
>>> import gocept.lms.notify
>>> gocept.lms.notify.ServerProxy = xmlrpc = XMLRPCDummy()
+>>> import datetime
+>>> gocept.lms.notify.INTERVAL = datetime.timedelta(seconds=0)
+
+
+Sending out notifications
+=========================
When run with an empty database, nothing happens:
(at)(at) -52,19 +58,70 (at)(at)
Connect: None
Update many states: fred - 3
-Running another notification would not produce any actions, because Fred was
successfully notified:
+Running another notification would not produce any actions, because Fred was
+successfully notified:
>>> notify()
>>> xmlrpc.show_log()
When Fred subscribes to another URL that has a `last state change` date
-befor his last notification he will not receive a notification from this
+before his last notification he will not receive a notification from this
component (those status updates are handled by the XML-RPC interface):
>>> fred.register_urls([url4])
>>> notify()
>>> xmlrpc.show_log()
+
+Suppressing notifications
+=========================
+
+There are two conditions for a client to not be notified. The first is if the
+client's notifications are disabled:
+
+>>> fred.last_notification = fred.__class__.last_notification
+>>> fred.notify = False
+>>> notify()
+>>> xmlrpc.show_log()
+
+The client's last notification date has not been updated because he didn't
+receive a notification:
+
+>>> fred.last_notification
+datetime.datetime(1970, 1, 1, 0, 0, tzinfo=<UTC>)
+
+Clean-up:
+
+>>> fred.notify = True
+
+The second is if the client should receive notifications but has received one
+a short time ago:
+
+>>> import pytz
+>>> now = datetime.datetime.now(pytz.UTC)
+>>> fred.last_notification = now
+>>> gocept.lms.notify.INTERVAL = datetime.timedelta(seconds=2)
+
+Ensure that a URL was changed recently enough for the client to be notified
+about it:
+
+>>> url1.last_state_change = now
+>>> import zope.event, zope.lifecycleevent
+>>> zope.event.notify(zope.lifecycleevent.ObjectModifiedEvent(url1))
+
+>>> notify()
+>>> xmlrpc.show_log()
+
+After the interval has elapsed, the client will receive notifications again:
+
+>>> import time
+>>> time.sleep(2.1)
+>>> notify()
+>>> xmlrpc.show_log()
+Connect: None
+Update many states: fred - 1
+
+
.. [#functionaltest] Setup functional test
>>> import gocept.lms.app
|
SVN: r6086 - gocept.lms/trunk/src/gocept/lms
Thomas Lotze <tl(at)gocept.com> |
2008-07-16 10:26:21 |
[ FULL ]
|
Author: thomas
Date: Wed Jul 16 10:26:18 2008
New Revision: 6086
Log:
refactored client and notifications: better structure, more readability
Modified:
gocept.lms/trunk/src/gocept/lms/app.py
gocept.lms/trunk/src/gocept/lms/client.py
gocept.lms/trunk/src/gocept/lms/interfaces.py
gocept.lms/trunk/src/gocept/lms/notify.py
gocept.lms/trunk/src/gocept/lms/notify.txt
Modified: gocept.lms/trunk/src/gocept/lms/app.py
==============================================================================
--- gocept.lms/trunk/src/gocept/lms/app.py (original)
+++ gocept.lms/trunk/src/gocept/lms/app.py Wed Jul 16 10:26:18 2008
(at)(at) -123,11 +123,11 (at)(at)
(at)authenticatedClient
def getClientNotifications(self, client, password):
- return client.notify
+ return gocept.lms.interfaces.INotifications(client).enabled
(at)authenticatedClient
def setClientNotifications(self, client, password, status):
- client.notify = bool(status)
+ gocept.lms.interfaces.INotifications(client).enabled = bool(status)
(at)authenticatedClient
def registerURLs(self, client, password, urls):
Modified: gocept.lms/trunk/src/gocept/lms/client.py
==============================================================================
--- gocept.lms/trunk/src/gocept/lms/client.py (original)
+++ gocept.lms/trunk/src/gocept/lms/client.py Wed Jul 16 10:26:18 2008
(at)(at) -2,9 +2,14 (at)(at)
# See also LICENSE.txt
import datetime
+import xmlrpclib
+
import pytz
import BTrees
import grok
+from hurry.query import Ge
+from hurry.query.set import AnyOf
+import hurry.query.interfaces
import zope.interface
import zope.component
import zope.event
(at)(at) -15,6 +20,10 (at)(at)
import gocept.lms.interfaces
+# Provide hook for tests to set up dummies
+ServerProxy = xmlrpclib.ServerProxy
+
+
class ClientContainer(grok.Container):
zope.interface.implements(gocept.lms.interfaces.IClientProvider)
(at)(at) -31,9 +40,6 (at)(at)
password = None
contact_name = None
contact_email = None
- notify = True
- last_notification = datetime.datetime(1970, 1, 1, tzinfo=pytz.UTC)
- failed_notifications = 0
callback = None
urls = gocept.reference.ReferenceCollection(ensure_integrity=True)
(at)(at) -53,3 +59,42 (at)(at)
def iter_urls(self):
return iter(self.urls)
+
+ def notify(self):
+ """Send notifications about recently changed URLs."""
+ notifications = gocept.lms.interfaces.INotifications(self)
+ url_query = zope.component.getUtility(hurry.query.interfaces.IQuery)
+ urls = url_query.searchResults(
+ Ge(('urls', 'last_state_change'), notifications.last) &
+ AnyOf(('urls', 'clients'), [self]))
+ if not urls:
+ # No URLs have changed since last time. Nothing to do.
+ return
+
+ # XXX Memory usage
+ notifications = [(url.url, url.state, url.reason) for url in urls]
+ self_xmlrpc = ServerProxy(self.callback)
+ self_xmlrpc.updateManyStates(self.id, self.password, notifications)
+
+
+class Notifications(grok.Annotation, grok.Model):
+
+ grok.provides(gocept.lms.interfaces.INotifications)
+ grok.context(gocept.lms.interfaces.INotificationRecipient)
+
+ enabled = True
+ last = datetime.datetime(1970, 1, 1, tzinfo=pytz.UTC)
+ failed = 0
+
+ def notify(self):
+ """Perform notifications on the recipient."""
+ try:
+ self.__parent__.notify()
+ except:
+ # XXX logging
+ self.failed += 1
+ if self.failed > 20:
+ self.enabled = False
+ else:
+ self.failed = 0
+ self.last = datetime.datetime.now(pytz.UTC)
Modified: gocept.lms/trunk/src/gocept/lms/interfaces.py
==============================================================================
--- gocept.lms/trunk/src/gocept/lms/interfaces.py (original)
+++ gocept.lms/trunk/src/gocept/lms/interfaces.py Wed Jul 16 10:26:18 2008
(at)(at) -80,7 +80,37 (at)(at)
"""Retrieve a Client object by Id."""
-class IClient(zope.interface.Interface):
+class INotifications(zope.interface.Interface):
+ """Manage notifications for a recipient."""
+
+ enabled = zope.schema.Bool(
+ title=u'Notify?',
+ default=True)
+
+ last = zope.schema.Datetime(
+ title=u'Last notified')
+
+ failed = zope.schema.Int(
+ title=u'Number of failed notifications',
+ default=0)
+
+ def notify():
+ """Perform notifications on the recipient."""
+
+
+class INotificationRecipient(zope.interface.Interface):
+ """A physical notification recipient such as a client.
+
+ Provides a specific 'over-the-wire' implementation of how to notify the
+ recipient.
+
+ """
+
+ def notify():
+ """Send notifications."""
+
+
+class IClient(INotificationRecipient):
id = zope.schema.TextLine(
title=u'Client Id',
(at)(at) -96,17 +126,6 (at)(at)
contact_email = z3c.schema.email.RFC822MailAddress(
title=u'Contact e-mail address')
- notify = zope.schema.Bool(
- title=u'Notify?',
- default=True)
-
- last_notification = zope.schema.Datetime(
- title=u'Last notified')
-
- failed_notifications = zope.schema.Int(
- title=u'Number of failed notifications',
- default=0)
-
callback = zope.schema.URI(
title=u'Callback URL')
Modified: gocept.lms/trunk/src/gocept/lms/notify.py
==============================================================================
--- gocept.lms/trunk/src/gocept/lms/notify.py (original)
+++ gocept.lms/trunk/src/gocept/lms/notify.py Wed Jul 16 10:26:18 2008
(at)(at) -2,55 +2,25 (at)(at)
# See also LICENSE.txt
import datetime
-
import pytz
-
-from hurry.query import Ge
-from hurry.query.set import AnyOf
-import hurry.query.interfaces
import zope.component
-
import gocept.lms.interfaces
-import xmlrpclib
-
INTERVAL = datetime.timedelta(seconds=5*60)
-# Provide hook for tests to set up dummies
-ServerProxy = xmlrpclib.ServerProxy
-
-
def notify():
- url_query = zope.component.getUtility(hurry.query.interfaces.IQuery)
-
reference_time = datetime.datetime.now(pytz.UTC) - INTERVAL
# Notify each client about URL changes that happened since the last
# notification.
clients = zope.component.getUtility(gocept.lms.interfaces.IClientProvider)
for client in clients.values():
- if not client.notify:
+ notifications = gocept.lms.interfaces.INotifications(client)
+ if not notifications.enabled:
continue
- if client.last_notification > reference_time:
+ if notifications.last > reference_time:
# don't notify clients more frequently than every 5 minutes
continue
- urls = url_query.searchResults(
- Ge(('urls', 'last_state_change'), client.last_notification) &
- AnyOf(('urls', 'clients'), [client]))
- if not urls:
- # No URLs have changed since last time. Just ignore this client.
- continue
- # XXX Memory usage
- notifications = [(url.url, url.state, url.reason) for url in urls]
- try:
- client_xmlrpc = ServerProxy(client.callback)
- client_xmlrpc.updateManyStates(client.id, client.password,
notifications)
- except:
- client.failed_notifications += 1
- if client.failed_notifications > 20:
- client.notify = False
- else:
- client.failed_notifications = 0
- client.last_notification = datetime.datetime.now(pytz.UTC)
+ notifications.notify()
Modified: gocept.lms/trunk/src/gocept/lms/notify.txt
==============================================================================
--- gocept.lms/trunk/src/gocept/lms/notify.txt (original)
+++ gocept.lms/trunk/src/gocept/lms/notify.txt Wed Jul 16 10:26:18 2008
(at)(at) -21,7 +21,7 (at)(at)
... print '\n'.join(self.log)
... self.log = []
>>> import gocept.lms.notify
->>> gocept.lms.notify.ServerProxy = xmlrpc = XMLRPCDummy()
+>>> gocept.lms.client.ServerProxy = xmlrpc = XMLRPCDummy()
>>> import datetime
>>> gocept.lms.notify.INTERVAL = datetime.timedelta(seconds=0)
(at)(at) -79,27 +79,28 (at)(at)
There are two conditions for a client to not be notified. The first is if the
client's notifications are disabled:
->>> fred.last_notification = fred.__class__.last_notification
->>> fred.notify = False
+>>> fred_notifications = gocept.lms.interfaces.INotifications(fred)
+>>> fred_notifications.last = fred_notifications.__class__.last
+>>> fred_notifications.enabled = False
>>> notify()
>>> xmlrpc.show_log()
The client's last notification date has not been updated because he didn't
receive a notification:
->>> fred.last_notification
+>>> fred_notifications.last
datetime.datetime(1970, 1, 1, 0, 0, tzinfo=<UTC>)
Clean-up:
->>> fred.notify = True
+>>> fred_notifications.enabled = True
The second is if the client should receive notifications but has received one
a short time ago:
>>> import pytz
>>> now = datetime.datetime.now(pytz.UTC)
->>> fred.last_notification = now
+>>> fred_notifications.last = now
>>> gocept.lms.notify.INTERVAL = datetime.timedelta(seconds=2)
Ensure that a URL was changed recently enough for the client to be notified
|
SVN: r6087 - gocept.lms/trunk/src/gocept/lms
Thomas Lotze <tl(at)gocept.com> |
2008-07-16 11:33:23 |
[ FULL ]
|
Author: thomas
Date: Wed Jul 16 11:33:20 2008
New Revision: 6087
Log:
started working on the checker: implemented the thread pool and the one-time
check runner
Added:
gocept.lms/trunk/src/gocept/lms/check.py (contents, props changed)
gocept.lms/trunk/src/gocept/lms/check.txt (contents, props changed)
Modified:
gocept.lms/trunk/src/gocept/lms/interfaces.py
gocept.lms/trunk/src/gocept/lms/tests.py
Added: gocept.lms/trunk/src/gocept/lms/check.py
==============================================================================
--- (empty file)
+++ gocept.lms/trunk/src/gocept/lms/check.py Wed Jul 16 11:33:20 2008
(at)(at) -0,0 +1,67 (at)(at)
+# Copyright (c) 2008 gocept gmbh & co. kg
+# See also LICENSE.txt
+
+import datetime
+import threading
+
+import pytz
+
+import grok
+import zc.queue.interfaces
+import zope.component
+import zope.interface
+
+import gocept.lms.interfaces
+
+
+INTERVAL = datetime.timedelta(seconds=5*60)
+
+THREADS = 20
+
+
+def check():
+ """Pull URLs from the check queue and have them checked.
+
+ Does so as long as there are threads available.
+
+ """
+ check_queue = zope.component.getUtility(zc.queue.interfaces.IQueue,
+ name='check')
+ thread_pool = zope.component.getUtility(gocept.lms.interfaces.IThreadPool)
+
+ while True:
+ if not thread_pool.threads.acquire(blocking=False):
+ break
+ try:
+ url = check_queue.pull()
+ except:
+ thread_pool.threads.release()
+ break
+
+ thread = CheckerThread(url.url)
+ thread.start()
+ thread_pool.active.add(thread)
+
+
+class ThreadPool(grok.GlobalUtility):
+
+ zope.interface.implements(gocept.lms.interfaces.IThreadPool)
+
+ def __init__(self):
+ self.threads = threading.Semaphore(THREADS)
+ self.active = set()
+
+
+class CheckerThread(threading.Thread):
+
+ zope.interface.implements(gocept.lms.interfaces.ICheckerThread)
+
+ state = None
+ reason = None
+
+ def __init__(self, url):
+ super(CheckerThread, self).__init__()
+ self.url = url
+
+ def run(self):
+ pass
Added: gocept.lms/trunk/src/gocept/lms/check.txt
==============================================================================
--- (empty file)
+++ gocept.lms/trunk/src/gocept/lms/check.txt Wed Jul 16 11:33:20 2008
(at)(at) -0,0 +1,114 (at)(at)
+===============
+The URL checker
+===============
+
+The checker pulls URLs from the check queue and checks them[#functionaltest]_.
+
+
+Pulling URLs from the check queue
+=================================
+
+A thread pool is used for managing worker threads. We reduce the maximum
+number of concurrent active threads for this test:
+
+>>> from zope.component import getUtility
+>>> import gocept.lms.interfaces
+>>> import threading
+>>> thread_pool = getUtility(gocept.lms.interfaces.IThreadPool)
+>>> thread_pool.threads = threading.Semaphore(3)
+>>> thread_pool.active
+set([])
+>>> thread_pool.threads._Semaphore__value
+3
+
+If the check queue is empty, running the checker will not create any worker
+threads:
+
+>>> from gocept.lms.check import check
+>>> check()
+>>> thread_pool.active
+set([])
+>>> thread_pool.threads._Semaphore__value
+3
+
+We create some URLs:
+
+>>> urls =
zope.component.getUtility(gocept.lms.interfaces.IURLProvider)
+>>> url1 = urls.add('http://example.com/1')
+>>> url2 = urls.add('http://example.com/2')
+>>> url3 = urls.add('http://example.com/3')
+>>> url4 = urls.add('http://example.com/4')
+>>> url5 = urls.add('http://example.com/5')
+
+Now put the first one in the check queue:
+
+>>> import zc.queue.interfaces
+>>> check_queue =
zope.component.getUtility(zc.queue.interfaces.IQueue,
+... name='check')
+>>> check_queue.put(url1)
+
+The checker will empty the queue and create one worker thread:
+
+>>> check()
+>>> list(check_queue)
+[]
+>>> t1 = list(thread_pool.active)[0]
+>>> t1.join(2)
+>>> thread_pool.active
+set([<CheckerThread(Thread-1, stopped)>])
+>>> thread_pool.threads._Semaphore__value
+2
+
+Two more URLs can be checked until the thread limit is reached:
+
+>>> check_queue.put(url2)
+>>> check_queue.put(url3)
+>>> check()
+>>> list(check_queue)
+[]
+>>> _ = [t.join(2) for t in thread_pool.active]
+>>> sorted(thread_pool.active, key=lambda t:t.getName())
+[<CheckerThread(Thread-1, stopped)>,
+ <CheckerThread(Thread-2, stopped)>,
+ <CheckerThread(Thread-3, stopped)>]
+>>> thread_pool.threads._Semaphore__value
+0
+
+Now the checker cannot create any more worker threads. It will not take URLs
+from the queue:
+
+>>> check_queue.put(url4)
+>>> check()
+>>> list(check_queue)
+[<gocept.lms.url.URL 'http://example.com/4'>]
+>>> len(thread_pool.active)
+3
+>>> thread_pool.threads._Semaphore__value
+0
+
+After releasing one thread on the semaphore, we can continue to pull URLs from
+the queue. Remaining URLs that cannot be pulled because threads are used up
+again will stay in the queue:
+
+>>> thread_pool.threads.release()
+>>> check_queue.put(url5)
+>>> check()
+>>> list(check_queue)
+[<gocept.lms.url.URL 'http://example.com/5'>]
+>>> _ = [t.join(2) for t in thread_pool.active]
+>>> len(thread_pool.active)
+4
+>>> thread_pool.threads._Semaphore__value
+0
+
+
+.. [#functionaltest] Setup functional test
+
+ >>> import gocept.lms.app
+ >>> root = getRootFolder()
+ >>> import zope.app.component.hooks
+ >>> old_site = zope.app.component.hooks.getSite()
+ >>> zope.app.component.hooks.setSite(root)
+
+ >>> root['app'] = gocept.lms.app.LMS()
+ >>> zope.app.component.hooks.setSite(root['app'])
Modified: gocept.lms/trunk/src/gocept/lms/interfaces.py
==============================================================================
--- gocept.lms/trunk/src/gocept/lms/interfaces.py (original)
+++ gocept.lms/trunk/src/gocept/lms/interfaces.py Wed Jul 16 11:33:20 2008
(at)(at) -138,3 +138,27 (at)(at)
urls: an iterable of IURL objects
"""
+
+
+class IThreadPool(zope.interface.Interface):
+ """Thread pool for the checker."""
+
+ threads = zope.interface.Attribute(
+ u'Semaphore limiting the number of concurrent active threads')
+
+ active = zope.interface.Attribute(u'Set of active threads')
+
+
+class ICheckerThread(zope.interface.Interface):
+
+ url = zope.schema.URI(
+ title=u'URL')
+
+ state = zope.schema.Choice(
+ title=u'State',
+ source=StateSource(),
+ required=False)
+
+ reason = zope.schema.TextLine(
+ title=u'Reason for state',
+ required=False)
Modified: gocept.lms/trunk/src/gocept/lms/tests.py
==============================================================================
--- gocept.lms/trunk/src/gocept/lms/tests.py (original)
+++ gocept.lms/trunk/src/gocept/lms/tests.py Wed Jul 16 11:33:20 2008
(at)(at) -24,7 +24,7 (at)(at)
'url.txt',
optionflags=flags)
functional = zope.app.testing.functional.FunctionalDocFileSuite(
- 'app.txt', 'schedule.txt', 'xmlrpc.txt', 'notify.txt',
+ 'app.txt', 'check.txt', 'schedule.txt', 'xmlrpc.txt', 'notify.txt',
optionflags=flags)
functional.layer = FunctionalLayer
return unittest.TestSuite([unit, functional])
|
SVN: r6088 - gocept.lms/trunk/src/gocept/lms
Thomas Lotze <tl(at)gocept.com> |
2008-07-16 11:55:08 |
[ FULL ]
|
Author: thomas
Date: Wed Jul 16 11:55:06 2008
New Revision: 6088
Log:
changed the thread pool implementation to get rid of the semaphore
Modified:
gocept.lms/trunk/src/gocept/lms/check.py
gocept.lms/trunk/src/gocept/lms/check.txt
gocept.lms/trunk/src/gocept/lms/interfaces.py
Modified: gocept.lms/trunk/src/gocept/lms/check.py
==============================================================================
--- gocept.lms/trunk/src/gocept/lms/check.py (original)
+++ gocept.lms/trunk/src/gocept/lms/check.py Wed Jul 16 11:55:06 2008
(at)(at) -16,8 +16,6 (at)(at)
INTERVAL = datetime.timedelta(seconds=5*60)
-THREADS = 20
-
def check():
"""Pull URLs from the check queue and have them checked.
(at)(at) -30,14 +28,12 (at)(at)
thread_pool = zope.component.getUtility(gocept.lms.interfaces.IThreadPool)
while True:
- if not thread_pool.threads.acquire(blocking=False):
+ if not thread_pool.available:
break
- try:
- url = check_queue.pull()
- except:
- thread_pool.threads.release()
+ if not check_queue:
break
+ url = check_queue.pull()
thread = CheckerThread(url.url)
thread.start()
thread_pool.active.add(thread)
(at)(at) -47,10 +43,18 (at)(at)
zope.interface.implements(gocept.lms.interfaces.IThreadPool)
+ limit = 20
+
def __init__(self):
- self.threads = threading.Semaphore(THREADS)
self.active = set()
+ (at)property
+ def available(self):
+ remaining = self.limit - len(self.active)
+ if remaining < 0:
+ return 0
+ return remaining
+
class CheckerThread(threading.Thread):
Modified: gocept.lms/trunk/src/gocept/lms/check.txt
==============================================================================
--- gocept.lms/trunk/src/gocept/lms/check.txt (original)
+++ gocept.lms/trunk/src/gocept/lms/check.txt Wed Jul 16 11:55:06 2008
(at)(at) -15,10 +15,10 (at)(at)
>>> import gocept.lms.interfaces
>>> import threading
>>> thread_pool = getUtility(gocept.lms.interfaces.IThreadPool)
->>> thread_pool.threads = threading.Semaphore(3)
+>>> thread_pool.limit = 3
>>> thread_pool.active
set([])
->>> thread_pool.threads._Semaphore__value
+>>> thread_pool.available
3
If the check queue is empty, running the checker will not create any worker
(at)(at) -28,7 +28,7 (at)(at)
>>> check()
>>> thread_pool.active
set([])
->>> thread_pool.threads._Semaphore__value
+>>> thread_pool.available
3
We create some URLs:
(at)(at) -56,7 +56,7 (at)(at)
>>> t1.join(2)
>>> thread_pool.active
set([<CheckerThread(Thread-1, stopped)>])
->>> thread_pool.threads._Semaphore__value
+>>> thread_pool.available
2
Two more URLs can be checked until the thread limit is reached:
(at)(at) -71,7 +71,7 (at)(at)
[<CheckerThread(Thread-1, stopped)>,
<CheckerThread(Thread-2, stopped)>,
<CheckerThread(Thread-3, stopped)>]
->>> thread_pool.threads._Semaphore__value
+>>> thread_pool.available
0
Now the checker cannot create any more worker threads. It will not take URLs
(at)(at) -83,22 +83,22 (at)(at)
[<gocept.lms.url.URL 'http://example.com/4'>]
>>> len(thread_pool.active)
3
->>> thread_pool.threads._Semaphore__value
+>>> thread_pool.available
0
-After releasing one thread on the semaphore, we can continue to pull URLs from
-the queue. Remaining URLs that cannot be pulled because threads are used up
-again will stay in the queue:
+After releasing one thread, we can continue to pull URLs from the queue.
+Remaining URLs that cannot be pulled because threads are used up again will
+stay in the queue:
->>> thread_pool.threads.release()
+>>> _ = thread_pool.active.pop()
>>> check_queue.put(url5)
>>> check()
>>> list(check_queue)
[<gocept.lms.url.URL 'http://example.com/5'>]
>>> _ = [t.join(2) for t in thread_pool.active]
>>> len(thread_pool.active)
-4
->>> thread_pool.threads._Semaphore__value
+3
+>>> thread_pool.available
0
Modified: gocept.lms/trunk/src/gocept/lms/interfaces.py
==============================================================================
--- gocept.lms/trunk/src/gocept/lms/interfaces.py (original)
+++ gocept.lms/trunk/src/gocept/lms/interfaces.py Wed Jul 16 11:55:06 2008
(at)(at) -143,11 +143,15 (at)(at)
class IThreadPool(zope.interface.Interface):
"""Thread pool for the checker."""
- threads = zope.interface.Attribute(
- u'Semaphore limiting the number of concurrent active threads')
+ limit = zope.schema.Int(
+ title=u'Maximum number of concurrent active threads')
active = zope.interface.Attribute(u'Set of active threads')
+ available = zope.schema.Int(
+ title=u'Number of currently available threads',
+ readonly=True)
+
class ICheckerThread(zope.interface.Interface):
|
SVN: r6098 - gocept.lms/trunk/profiles
Christian Theune <ct(at)gocept.com> |
2008-07-16 19:34:35 |
[ FULL ]
|
Author: ctheune
Date: Wed Jul 16 19:34:34 2008
New Revision: 6098
Log:
Remove i18n for now. This makes trouble with the lovely recipe.
Modified:
gocept.lms/trunk/profiles/base.cfg
Modified: gocept.lms/trunk/profiles/base.cfg
==============================================================================
--- gocept.lms/trunk/profiles/base.cfg (original)
+++ gocept.lms/trunk/profiles/base.cfg Wed Jul 16 19:34:34 2008
(at)(at) -1,6 +1,6 (at)(at)
[buildout]
develop = . gocept.reference
-parts = eggbasket app data zodb zeo lms i18n test runners scheduler checker
notifier
+parts = eggbasket app data zodb zeo lms test runners scheduler checker
notifier
extends = versions.cfg
# eggs will be installed in the default buildout location
# (see .buildout/default.cfg in your home directory)
(at)(at) -77,14 +77,6 (at)(at)
eggs = gocept.lms
defaults = ['--tests-pattern', '^f?tests$', '-v', '-c']
-# this section named so that the i18n scripts are called bin/i18n...
-[i18n]
-recipe = lovely.recipe:i18n
-package = gocept.lms
-domain = gocept.lms
-location = src/gocept/lms
-output = locales
-
[eggbasket]
recipe = z3c.recipe.eggbasket
eggs = grok
|
SVN: r6099 - gocept.lms/trunk/profiles
Christian Theune <ct(at)gocept.com> |
2008-07-16 20:10:54 |
[ FULL ]
|
Author: ctheune
Date: Wed Jul 16 20:10:52 2008
New Revision: 6099
Log:
remove duplicate server definition
Modified:
gocept.lms/trunk/profiles/base.cfg
Modified: gocept.lms/trunk/profiles/base.cfg
==============================================================================
--- gocept.lms/trunk/profiles/base.cfg (original)
+++ gocept.lms/trunk/profiles/base.cfg Wed Jul 16 20:10:52 2008
(at)(at) -67,10 +67,6 (at)(at)
storage 1
</zeoclient>
</zodb>
- <server>
- address ${lms:address}
- type HTTP
- </server>
[test]
recipe = zc.recipe.testrunner
|
SVN: r6103 - gocept.lms/trunk/src/gocept/lms
Christian Zagrodnick <cz(at)gocept.com> |
2008-07-17 10:11:35 |
[ FULL ]
|
Author: zagy
Date: Thu Jul 17 10:11:33 2008
New Revision: 6103
Log:
added unregisterURLs implementation
Modified:
gocept.lms/trunk/src/gocept/lms/app.py
gocept.lms/trunk/src/gocept/lms/app.txt
gocept.lms/trunk/src/gocept/lms/client.py
gocept.lms/trunk/src/gocept/lms/interfaces.py
gocept.lms/trunk/src/gocept/lms/url.py
gocept.lms/trunk/src/gocept/lms/xmlrpc.txt
Modified: gocept.lms/trunk/src/gocept/lms/app.py
==============================================================================
--- gocept.lms/trunk/src/gocept/lms/app.py (original)
+++ gocept.lms/trunk/src/gocept/lms/app.py Thu Jul 17 10:11:33 2008
(at)(at) -143,9 +143,13 (at)(at)
if url.state is not None]
return result
- def unregisterURLs(self, client_id, password, urls):
- # XXX API stub
- pass
+ (at)authenticatedClient
+ def unregisterURLs(self, client, password, urls):
+ url_objects = (url for url in
+ (self.url_provider.get_url(url) for url in urls)
+ if url is not None)
+ client.unregister_urls(url_objects)
+ return True
def getInfoFrameURL(self, client_id, password):
# XXX API stub
Modified: gocept.lms/trunk/src/gocept/lms/app.txt
==============================================================================
--- gocept.lms/trunk/src/gocept/lms/app.txt (original)
+++ gocept.lms/trunk/src/gocept/lms/app.txt Thu Jul 17 10:11:33 2008
(at)(at) -41,7 +41,7 (at)(at)
>>> fred.register_urls([urls.add('http://example.com/'),
... urls.add('http://example.com/asdf')])
->>> list(sorted(fred.iter_urls(), key=lambda x:x.url))
+>>> list(sorted(fred.iter_urls()))
[<gocept.lms.url.URL 'http://example.com/'>,
<gocept.lms.url.URL 'http://example.com/asdf'>]
(at)(at) -55,6 +55,24 (at)(at)
>>> len(list(example.clients))
1
+The URLs can be unregistered using the ``unreigster_urls`` method. When an URL
+is passed which is not registered for the client no error will be raised:
+
+>>> fred.unregister_urls(
+... [urls.get_url('http://example.com/'),
+... urls.add('http://not-registered-yet/')])
+>>> list(fred.iter_urls())
+[<gocept.lms.url.URL 'http://example.com/asdf'>]
+
+The URL http://example.com/ has no client
now:
+
+>>> list(example.clients)
+[]
+
+But /asdf still has
+>>> list(urls.get_url('http://example.com/asdf').clients)
+[<gocept.lms.client.Client object at 0x...>]
+
Clean up
--------
Modified: gocept.lms/trunk/src/gocept/lms/client.py
==============================================================================
--- gocept.lms/trunk/src/gocept/lms/client.py (original)
+++ gocept.lms/trunk/src/gocept/lms/client.py Thu Jul 17 10:11:33 2008
(at)(at) -52,12 +52,15 (at)(at)
def register_urls(self, urls):
self.urls.update(urls)
- references = zope.component.getUtility(
- zc.relation.interfaces.ICatalog, name='url_refs')
- references.index(self)
+ self._reindex(urls)
+
+ def unregister_urls(self, urls):
for url in urls:
- # Trigger re-indexing
- zope.event.notify(zope.lifecycleevent.ObjectModifiedEvent(url))
+ try:
+ self.urls.remove(url)
+ except KeyError:
+ pass
+ self._reindex(urls)
def iter_urls(self):
return iter(self.urls)
(at)(at) -78,6 +81,15 (at)(at)
self_xmlrpc = ServerProxy(self.callback)
self_xmlrpc.updateManyStates(self.id, self.password, notifications)
+ def _reindex(self, urls):
+ """Helper to reindex when urls change."""
+ references = zope.component.getUtility(
+ zc.relation.interfaces.ICatalog, name='url_refs')
+ references.index(self)
+ for url in urls:
+ # Trigger re-indexing
+ zope.event.notify(zope.lifecycleevent.ObjectModifiedEvent(url))
+
class Notifications(grok.Annotation, grok.Model):
Modified: gocept.lms/trunk/src/gocept/lms/interfaces.py
==============================================================================
--- gocept.lms/trunk/src/gocept/lms/interfaces.py (original)
+++ gocept.lms/trunk/src/gocept/lms/interfaces.py Thu Jul 17 10:11:33 2008
(at)(at) -139,6 +139,13 (at)(at)
"""
+ def unregister_urls(urls):
+ """Unregister URLs for client.
+
+ urls: an iterable of IURL objects
+
+ """
+
class IThreadPool(zope.interface.Interface):
"""Thread pool for the checker."""
Modified: gocept.lms/trunk/src/gocept/lms/url.py
==============================================================================
--- gocept.lms/trunk/src/gocept/lms/url.py (original)
+++ gocept.lms/trunk/src/gocept/lms/url.py Thu Jul 17 10:11:33 2008
(at)(at) -49,6 +49,11 (at)(at)
return "<%s.%s '%s'>" % (
__name__, self.__class__.__name__, self.url)
+ def __cmp__(self, other):
+ if isinstance(other, URL):
+ return cmp(self.url, other.url)
+ return -1
+
(at)property
def clients(self):
references = zope.component.getUtility(
Modified: gocept.lms/trunk/src/gocept/lms/xmlrpc.txt
==============================================================================
--- gocept.lms/trunk/src/gocept/lms/xmlrpc.txt (original)
+++ gocept.lms/trunk/src/gocept/lms/xmlrpc.txt Thu Jul 17 10:11:33 2008
(at)(at) -79,8 +79,8 (at)(at)
>>> clients =
zope.component.getUtility(gocept.lms.interfaces.IClientProvider)
>>> list(clients)
[u'gocept']
->>> gocept = clients.get('gocept')
->>> list(gocept.iter_urls())
+>>> cl_gocept = clients.get('gocept')
+>>> list(cl_gocept.iter_urls())
[<gocept.lms.url.URL 'http://example.com/url1'>,
<gocept.lms.url.URL 'http://example.com/url2'>]
(at)(at) -122,6 +122,30 (at)(at)
XXX what happens when invalid urls are registered?
+
+
+unregisterURLs
+==============
+
+The client calls ``unregisterURLs`` if he doesn't want to get further
+notifications for URLs[#unregisterURLs-auth]_:
+
+>>> server.unregisterURLs(
+... 'gocept', password,
+... ['http://example.com/url2',
+... 'http://example.com/url3'])
+True
+
+After calling unregisterURLs those URLs are no longer int he client's
+list[#functionaltest]_:
+
+>>> transaction.abort()
+>>> list(cl_gocept.iter_urls())
+[<gocept.lms.url.URL 'http://example.com/url1'>]
+
+>>> zope.app.component.hooks.setSite(old_site)
+
+
Setting/getting the notification status
=======================================
(at)(at) -149,7 +173,6 (at)(at)
Various API methods, currently implemented as stubs
===================================================
->>> server.unregisterURLs('gocept', password, ['http://localhost'])
>>> server.getInfoFrameURL('gocept', password)
'http://localhost:8080/lms'
(at)(at) -161,6 +184,13 (at)(at)
...
ProtocolError: <ProtocolError for localhost/app/: 401 401
Unauthorized>
+.. [#unregisterURLs-auth] unregisterURLs needs authentication:
+
+ >>> server.unregisterURLs('gocept', 'bsdf', [])
+ Traceback (most recent call last):
+ ...
+ ProtocolError: <ProtocolError for localhost/app/: 401 401
Unauthorized>
+
.. [#functionaltest] Setup functional test
>>> zope.app.component.hooks.setSite(root['app'])
|
SVN: r6111 - gocept.lms/trunk
Christian Zagrodnick <cz(at)gocept.com> |
2008-07-17 14:45:44 |
[ FULL ]
|
Author: zagy
Date: Thu Jul 17 14:45:43 2008
New Revision: 6111
Log:
sorted dependencies
Modified:
gocept.lms/trunk/setup.py
Modified: gocept.lms/trunk/setup.py
==============================================================================
--- gocept.lms/trunk/setup.py (original)
+++ gocept.lms/trunk/setup.py Thu Jul 17 14:45:43 2008
(at)(at) -18,19 +18,19 (at)(at)
zip_safe=False,
install_requires=[
'decorator',
+ 'gocept.reference>=0.4dev',
'grok',
'hurry.query',
'setuptools',
'z3c.schema',
'z3c.testsetup',
'zc.catalog',
- 'zc.relation',
'zc.queue',
+ 'zc.relation',
'zc.sourcefactory',
- 'zope.testing',
'zope.app.twisted',
'zope.app.wsgi',
- 'gocept.reference>=0.4dev'
+ 'zope.testing',
],
entry_points = dict(
console_scripts =
|
SVN: r6116 - gocept.form/tags/0.7.5
Christian Zagrodnick <cz(at)gocept.com> |
2008-07-17 16:15:30 |
[ FULL ]
|
Author: zagy
Date: Thu Jul 17 16:15:29 2008
New Revision: 6116
Log:
tagging 0.7.5
Added:
gocept.form/tags/0.7.5/
- copied from r6115, gocept.form/trunk/
|
SVN: r6117 - gocept.form/tags/0.7.5
Christian Zagrodnick <cz(at)gocept.com> |
2008-07-17 16:15:51 |
[ FULL ]
|
Author: zagy
Date: Thu Jul 17 16:15:50 2008
New Revision: 6117
Log:
0.7.5
Modified:
gocept.form/tags/0.7.5/setup.py
Modified: gocept.form/tags/0.7.5/setup.py
==============================================================================
--- gocept.form/tags/0.7.5/setup.py (original)
+++ gocept.form/tags/0.7.5/setup.py Thu Jul 17 16:15:50 2008
(at)(at) -9,7 +9,7 (at)(at)
setup(
name = 'gocept.form',
- version = "0.7.5dev",
+ version = "0.7.5",
author = "Christian Zagrodnick",
author_email = "cz(at)gocept.com",
description = "Extensions for zope.formlib",
|
SVN: r6118 - gocept.form/trunk
Christian Zagrodnick <cz(at)gocept.com> |
2008-07-17 16:16:45 |
[ FULL ]
|
Author: zagy
Date: Thu Jul 17 16:16:44 2008
New Revision: 6118
Log:
vb
Modified:
gocept.form/trunk/README.txt
gocept.form/trunk/setup.py
Modified: gocept.form/trunk/README.txt
==============================================================================
--- gocept.form/trunk/README.txt (original)
+++ gocept.form/trunk/README.txt Thu Jul 17 16:16:44 2008
(at)(at) -31,6 +31,9 (at)(at)
Changes
=======
+0.7.6 (unreleased)
+------------------
+
0.7.5 (2008-07-17)
------------------
Modified: gocept.form/trunk/setup.py
==============================================================================
--- gocept.form/trunk/setup.py (original)
+++ gocept.form/trunk/setup.py Thu Jul 17 16:16:44 2008
(at)(at) -9,7 +9,7 (at)(at)
setup(
name = 'gocept.form',
- version = "0.7.5dev",
+ version = "0.7.6dev",
author = "Christian Zagrodnick",
author_email = "cz(at)gocept.com",
description = "Extensions for zope.formlib",
|
SVN: r6127 - gocept.form/tags/0.7.6
Christian Zagrodnick <cz(at)gocept.com> |
2008-07-17 17:37:14 |
[ FULL ]
|
Author: zagy
Date: Thu Jul 17 17:37:13 2008
New Revision: 6127
Log:
tagging 0.7.6
Added:
gocept.form/tags/0.7.6/
- copied from r6126, gocept.form/trunk/
|
SVN: r6128 - gocept.form/tags/0.7.6
Christian Zagrodnick <cz(at)gocept.com> |
2008-07-17 17:37:37 |
[ FULL ]
|
Author: zagy
Date: Thu Jul 17 17:37:36 2008
New Revision: 6128
Log:
0.7.6
Modified:
gocept.form/tags/0.7.6/setup.py
Modified: gocept.form/tags/0.7.6/setup.py
==============================================================================
--- gocept.form/tags/0.7.6/setup.py (original)
+++ gocept.form/tags/0.7.6/setup.py Thu Jul 17 17:37:36 2008
(at)(at) -9,7 +9,7 (at)(at)
setup(
name = 'gocept.form',
- version = "0.7.6dev",
+ version = "0.7.6",
author = "Christian Zagrodnick",
author_email = "cz(at)gocept.com",
description = "Extensions for zope.formlib",
|
SVN: r6138 - gocept.lms/trunk/src/gocept/lms
Christian Zagrodnick <cz(at)gocept.com> |
2008-07-18 13:44:57 |
[ FULL ]
|
Author: zagy
Date: Fri Jul 18 13:44:56 2008
New Revision: 6138
Log:
different msg on darwin
Modified:
gocept.lms/trunk/src/gocept/lms/ftp.txt
Modified: gocept.lms/trunk/src/gocept/lms/ftp.txt
==============================================================================
--- gocept.lms/trunk/src/gocept/lms/ftp.txt (original)
+++ gocept.lms/trunk/src/gocept/lms/ftp.txt Fri Jul 18 13:44:56 2008
(at)(at) -32,4 +32,4 (at)(at)
If the server doesn't respond, we mark it as `unavailable` as well:
>>> handler.check('ftp://no.server.example/knuddlhurz')
-('unavailable', 'Name or service not known')
+('unavailable', '...not known')
|
SVN: r6150 - gocept.lms/trunk
Christian Theune <ct(at)gocept.com> |
2008-07-21 14:49:11 |
[ FULL ]
|
Author: ctheune
Date: Mon Jul 21 14:49:10 2008
New Revision: 6150
Log:
Remove external for gocept.munin again, only the plugin script needs this and
that runs with the system python.
Modified:
gocept.lms/trunk/ (props changed)
|
SVN: r6153 - gocept.sequence/tags
Sebastian Wehrmann <sw(at)gocept.com> |
2008-07-21 15:15:17 |
[ FULL ]
|
Author: sweh
Date: Mon Jul 21 15:15:15 2008
New Revision: 6153
Log:
create tags directory
Added:
gocept.sequence/tags/
|
SVN: r6154 - gocept.sequence/tags/0.3dev
Sebastian Wehrmann <sw(at)gocept.com> |
2008-07-21 15:16:22 |
[ FULL ]
|
Author: sweh
Date: Mon Jul 21 15:16:21 2008
New Revision: 6154
Log:
copy trunk to new 0.3dev tag
Added:
gocept.sequence/tags/0.3dev/
- copied from r6153, gocept.sequence/trunk/
|
SVN: r6155 - in gocept.sequence/tags: 0.3 0.3dev
Sebastian Wehrmann <sw(at)gocept.com> |
2008-07-21 15:18:06 |
[ FULL ]
|
Author: sweh
Date: Mon Jul 21 15:18:06 2008
New Revision: 6155
Log:
remove the dev in tag
Added:
gocept.sequence/tags/0.3/
- copied from r6154, gocept.sequence/tags/0.3dev/
Removed:
gocept.sequence/tags/0.3dev/
|
SVN: r6156 - gocept.sequence/tags/0.3
Sebastian Wehrmann <sw(at)gocept.com> |
2008-07-21 15:19:17 |
[ FULL ]
|
Author: sweh
Date: Mon Jul 21 15:19:16 2008
New Revision: 6156
Log:
change version
Modified:
gocept.sequence/tags/0.3/setup.py
Modified: gocept.sequence/tags/0.3/setup.py
==============================================================================
--- gocept.sequence/tags/0.3/setup.py (original)
+++ gocept.sequence/tags/0.3/setup.py Mon Jul 21 15:19:16 2008
(at)(at) -4,7 +4,7 (at)(at)
def read(*rnames):
return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
-version = '0.2dev'
+version = '0.3'
setup(name='gocept.sequence',
version=version,
|
SVN: r6167 - gocept.sequence/tags/0.31
Sebastian Wehrmann <sw(at)gocept.com> |
2008-07-22 10:05:56 |
[ FULL ]
|
Author: sweh
Date: Tue Jul 22 10:05:55 2008
New Revision: 6167
Log:
create release tag
Added:
gocept.sequence/tags/0.31/
- copied from r6166, gocept.sequence/trunk/
|
SVN: r6168 - gocept.sequence/tags/0.31
Sebastian Wehrmann <sw(at)gocept.com> |
2008-07-22 10:06:40 |
[ FULL ]
|
Author: sweh
Date: Tue Jul 22 10:06:39 2008
New Revision: 6168
Log:
change version
Modified:
gocept.sequence/tags/0.31/setup.py
Modified: gocept.sequence/tags/0.31/setup.py
==============================================================================
--- gocept.sequence/tags/0.31/setup.py (original)
+++ gocept.sequence/tags/0.31/setup.py Tue Jul 22 10:06:39 2008
(at)(at) -4,7 +4,7 (at)(at)
def read(*rnames):
return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
-version = '0.4dev'
+version = '0.31'
setup(name='gocept.sequence',
version=version,
|
SVN: r6319 - gocept.imapapi
Christian Theune <ct(at)gocept.com> |
2008-07-22 10:43:34 |
[ FULL ]
|
Author: ctheune
Date: Tue Jul 22 10:43:33 2008
New Revision: 6319
Log:
Create separate project are for the IMAPAPI.
Added:
gocept.imapapi/
|
SVN: r6325 - gocept.sequence/trunk
Thomas Lotze <tl(at)gocept.com> |
2008-07-22 11:16:08 |
[ FULL ]
|
Author: thomas
Date: Tue Jul 22 11:16:06 2008
New Revision: 6325
Log:
rewrote the short package description
Modified:
gocept.sequence/trunk/README.txt
Modified: gocept.sequence/trunk/README.txt
==============================================================================
--- gocept.sequence/trunk/README.txt (original)
+++ gocept.sequence/trunk/README.txt Tue Jul 22 11:16:06 2008
(at)(at) -1,4 +1,6 (at)(at)
-This package lets you generate a persistent sequence. That means in practice,
-that you can generate sequent numbers without having to worry about storing
-the last generated number. This is done by gocept.sequence within the
-annotation of an object you provide.
+===============
+gocept.sequence
+===============
+
+This package generates increasing sequences of integer numbers associated with
+objects. It uses persistent annotations of those objects.
|
SVN: r6326 - gocept.recipe.env
Christian Theune <ct(at)gocept.com> |
2008-07-22 12:03:03 |
[ FULL ]
|
Author: ctheune
Date: Tue Jul 22 12:03:02 2008
New Revision: 6326
Log:
Create project area for gocept.recipe.env
Added:
gocept.recipe.env/
|
SVN: r6328 - gocept.recipe.env/trunk
Christian Theune <ct(at)gocept.com> |
2008-07-22 12:06:20 |
[ FULL ]
|
Author: ctheune
Date: Tue Jul 22 12:06:20 2008
New Revision: 6328
Log:
Remove garbage from import.
Removed:
gocept.recipe.env/trunk/.installed.cfg
gocept.recipe.env/trunk/svn-commit.tmp
|
SVN: r6329 - gocept.recipe.env/trunk
Christian Theune <ct(at)gocept.com> |
2008-07-22 12:06:54 |
[ FULL ]
|
Author: ctheune
Date: Tue Jul 22 12:06:53 2008
New Revision: 6329
Log:
start setting ignores
Modified:
gocept.recipe.env/trunk/ (props changed)
|
SVN: r6331 - gocept.recipe.env/tags
Christian Theune <ct(at)gocept.com> |
2008-07-22 12:51:54 |
[ FULL ]
|
Author: ctheune
Date: Tue Jul 22 12:51:53 2008
New Revision: 6331
Log:
Create tags area
Added:
gocept.recipe.env/tags/
|
SVN: r6332 - gocept.recipe.env/1.0
Christian Theune <ct(at)gocept.com> |
2008-07-22 12:52:10 |
[ FULL ]
|
Author: ctheune
Date: Tue Jul 22 12:52:09 2008
New Revision: 6332
Log:
Tag release
Added:
gocept.recipe.env/1.0/
- copied from r6331, gocept.recipe.env/trunk/
|
SVN: r6333 - gocept.recipe.env/trunk
Christian Theune <ct(at)gocept.com> |
2008-07-22 12:53:54 |
[ FULL ]
|
Author: ctheune
Date: Tue Jul 22 12:53:53 2008
New Revision: 6333
Log:
version bump and some textual cleanup
Modified:
gocept.recipe.env/trunk/CHANGES.txt
gocept.recipe.env/trunk/CONTRIBUTORS.txt
gocept.recipe.env/trunk/README.txt
gocept.recipe.env/trunk/setup.py
Modified: gocept.recipe.env/trunk/CHANGES.txt
==============================================================================
--- gocept.recipe.env/trunk/CHANGES.txt (original)
+++ gocept.recipe.env/trunk/CHANGES.txt Tue Jul 22 12:53:53 2008
(at)(at) -1,4 +1,4 (at)(at)
1.0 (2008-07-22)
================
- - Created recipe with ZopeSkel [Christian Theune <ct(at)gocept.com>].
+- Created recipe with ZopeSkel [Christian Theune <ct(at)gocept.com>].
Modified: gocept.recipe.env/trunk/CONTRIBUTORS.txt
==============================================================================
--- gocept.recipe.env/trunk/CONTRIBUTORS.txt (original)
+++ gocept.recipe.env/trunk/CONTRIBUTORS.txt Tue Jul 22 12:53:53 2008
(at)(at) -1,3 +1,3 (at)(at)
-Christian Theune <ct(at)gocept.com>, Author
-Thomas Lotze <tl(at)gocept.com>, Author
+* Christian Theune <ct(at)gocept.com>, Author
+* Thomas Lotze <tl(at)gocept.com>, Author
Modified: gocept.recipe.env/trunk/README.txt
==============================================================================
--- gocept.recipe.env/trunk/README.txt (original)
+++ gocept.recipe.env/trunk/README.txt Tue Jul 22 12:53:53 2008
(at)(at) -1,17 +1,4 (at)(at)
.. contents::
-.. Note to recipe author!
- ---------------------
- Update the following URLs to point to your:
-
- - code repository
- - bug tracker
- - questions/comments feedback mail
- (do not set a real mail, to avoid spams)
-
- Or remove it if not used.
-[...]
|
SVN: r6340 - gocept.imapapi/tags
Christian Theune <ct(at)gocept.com> |
2008-07-22 16:56:42 |
[ FULL ]
|
Author: ctheune
Date: Tue Jul 22 16:56:42 2008
New Revision: 6340
Log:
Create area for releases
Added:
gocept.imapapi/tags/
|
SVN: r6341 - gocept.imapapi/tags/0.1
Christian Theune <ct(at)gocept.com> |
2008-07-22 16:57:33 |
[ FULL ]
|
Author: ctheune
Date: Tue Jul 22 16:57:32 2008
New Revision: 6341
Log:
Mark 0.1, the initial public release.
Added:
gocept.imapapi/tags/0.1/
- copied from r6340, gocept.imapapi/trunk/
|
SVN: r6344 - gocept.lxml/trunk
Christian Zagrodnick <cz(at)gocept.com> |
2008-07-24 21:46:40 |
[ FULL ]
|
|