Merge lp:~mwhudson/launchpad/permit_timeout_from_features-on-participation-bug-861510 into lp:launchpad

Proposed by Michael Hudson-Doyle
Status: Merged
Approved by: Michael Hudson-Doyle
Approved revision: no longer in the source branch.
Merged at revision: 14143
Proposed branch: lp:~mwhudson/launchpad/permit_timeout_from_features-on-participation-bug-861510
Merge into: lp:launchpad
Diff against target: 344 lines (+84/-38)
11 files modified
lib/canonical/launchpad/scripts/__init__.py (+5/-5)
lib/canonical/launchpad/webapp/adapter.py (+5/-3)
lib/canonical/launchpad/webapp/authorization.py (+16/-1)
lib/canonical/launchpad/webapp/ftests/test_adapter.py (+0/-16)
lib/canonical/launchpad/webapp/interaction.py (+22/-1)
lib/canonical/launchpad/webapp/interfaces.py (+19/-0)
lib/canonical/launchpad/webapp/servers.py (+4/-2)
lib/canonical/launchpad/webapp/tests/test_servers.py (+3/-1)
lib/canonical/testing/layers.py (+9/-6)
lib/lp/code/tests/test_doc.py (+1/-1)
lib/lp/testing/__init__.py (+0/-2)
To merge this branch: bzr merge lp:~mwhudson/launchpad/permit_timeout_from_features-on-participation-bug-861510
Reviewer Review Type Date Requested Status
Benji York (community) code Approve
Martin Pool (community) Approve
Review via email: mp+78355@code.launchpad.net

Commit message

[r=benji,mbp][bug=623199,861510] Move permit_timeout_from_features flag from old-fashioned, incompletely-reset thread local storage to a new shiny method of attaching data to the interaction

Description of the change

Hi,

This branch does two things:

1) It creates a pattern for storing stuff in the participation (aka request in an appserver context) rather than thread local variables, and
2) Uses this new pattern to store the flag indicating whether to read the hard_timeout feature flag in this way rather on a thread local.

Part 2) fixes bug 861510, which could have been fixed in other ways, but I've been thinking about a way to do 1) and start fixing bug 623199. I have two and a half failed attempts to store the feature controller itself (only) on the participation, but they all got a bit confusing and I decided to pick an easier target (I wanted to fix _some_ problem in this way, to validate the technique). I quite like the fix -- because the flag defaults to False, I can kill off the half baked attempts we have to clear this flag when it needs to be cleared and can be confident that it can't escape the test isolation (this is one of the reasons I just landed a branch that unconditionally tears down the interaction between tests <wink>).

The core understanding I reached is that in Launchpad, the participation is only ever:

(a) an instance of canonical.launchpad.webapp.interaction.Participation (in scripts, mostly)
(b) an instance of canonical.launchpad.webapp.servers.LaunchpadTestRequest (in tests, clearly -- this is the participation type the lp.testing login helpers create by default)
(c) some subclass of canonical.launchpad.webapp.servers.BasicLaunchpadRequest (in the appserver)

So we only need to add an attribute to instances of these three classes and then we can confidently access it whenever there is a zope interaction set up (whenever we're "logged in" in some sense, although this includes the anonymous "user").

In the thread linked to from bug 623199, I proposed using the annotations dictionary that Launchpad's browser requests already have, but when push came to shove I didn't really see the point and just stuck another attribute on -- if we were to use annotations, we'd have to come up with a constant containing the key and import that around and it just felt unnecessary (also some page templates read the features attribute off the request already, so supporting them was easier this way in my previous branches).

I've successfully tested the branch in EC2.

Cheers,
mwh

To post a comment you must log in.
Revision history for this message
Martin Pool (mbp) wrote :

I'm no kind of authority on what is tasteful in Zope or Launchpad, but this does sound good to me.

I think you should fix your 'XXX explain more' ;-) by adding something similar to the text in <https://bugs.launchpad.net/launchpad/+bug/861510/comments/3>, otherwise people will ask, as I did, why you need special handling of the hard_timeout feature flag, rather than just looking it up in the usual way.

review: Needs Fixing
Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

Ah, I'd actually fixed that, but my ISP is having such a bad evening that my push had failed. It's pushed now (over 3G, sigh).

Revision history for this message
Martin Pool (mbp) wrote :

+1, but you definitely need review from someone else too

review: Approve
Revision history for this message
Benji York (benji) wrote :

The permit_timeout_from_features flag may have been conceived to help in
checking the timeout feature flag, but it seems to me that it applies to
all feature flags. Perhaps its name should be
"permit_feature_flag_lookup" and the feature flag code should raise an
exception if asked for a flag before the time is right.

Shouldn't the set_permit_timeout_from_features method and
_permit_feature_timeout thread local be removed since the new flag is
the "right" way to look up and mutate the flag?

Having get_participation_extras return None if no appropriate
participation is found feels like a trap to me (i.e., when someone calls
it they are implicitly asserting that the extras are available). It
should raise an exception instead and there should be a
query_participation_extras function so we can be explicit about
tolerating missing extras.

If it survives, the XXX in get_participation_extras is required to have
a bug and person's name associated with it. For details see
https://dev.launchpad.net/PolicyandProcess/XXXPolicy.

It feels just a little weird that get_participation_extras returns a
participation. I can't think of a design that feels better that doesn't
add an inappropriate level of complexity. Here's the best I could do in
case it inspires something better:

    Add an IHasParticpationExtras interface that only has a get_extras
    method. Participations that support extras would also provide
    IHasParticpationExtras and get_extras would return an
    IParticipationExtras.

In fact, I think the data should really be attached to the interaction
instead of the participation. That would remove the need to search
through the participations to find one with extras and the need to
assert that no more than one have extras. Since the participation is
entirely about associating a principle with the interaction and the
extras aren't principal-dependent, the interaction seems like the right
place to put the extras.

Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

Can we leave details of how this particular flag works to another merge proposal? This one is already confusing enough :-)

_permit_feature_timeout is not the thread local instance -- that instance is used for other things (that I'd also like to kill off, of course, but baby steps).

I agree in principle that stashing things on the interaction does seem cleaner in some ways. Maybe (sketching) something like this:

class IInteractionExtras(Interface):
    permit_timeout_from_features = Attribute(...)

class InteractionExtras(object):
    permit_timeout_from_features = False

class LaunchpadPermissiveSecurityPolicy(PermissiveSecurityPolicy):
    def __init__(self, *participations):
        PermissiveSecurityPolicy.__init__(self, *participations)
        self.extras = InteractionExtras()

(similar change to LaunchpadSecurityPolicy)

Then

def get_interaction_extras():
    # With some error checking, should fail if no interaction though
    return queryInteraction().extras

One part of this that feels, well, different to what I did is that it doesn't give a separate implementation for tests (LaunchpadTestRequest vs LaunchpadBrowserRequest). Maybe that's a good thing though.

What do you think?

Revision history for this message
Robert Collins (lifeless) wrote :

Re "The permit_timeout_from_features flag may have been conceived to help in
checking the timeout feature flag, but it seems to me that it applies to
all feature flags. Perhaps its name should be
"permit_feature_flag_lookup" and the feature flag code should raise an
exception if asked for a flag before the time is right."

No - its truely just the bootstrap mechanism for the db timeout
feature - there is -no- intent that other feature lookups, if they
happen before the db timeout is found, should be blocked (and it would
be a bad, surprising, bug to block them).

-Rob

Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

OK, I've made the changes I proposed and am kicking off a test in ec2. It's worked out to be a fairly small change, which is nice.

I probably should add a couple of docstrings but otherwise, please let me know what you think!

Revision history for this message
Benji York (benji) wrote :

Robert: thanks for explaining that the flag really is just about the
timeout flag and not more general. I see now why that is.

Revision history for this message
Benji York (benji) wrote :

> OK, I've made the changes I proposed and am kicking off a test in ec2.
> It's worked out to be a fairly small change, which is nice.
>
> I probably should add a couple of docstrings but otherwise, please let
> me know what you think!

I like it.

I'm still of the opinion that both get_ and query_ versions would be a
small win (the win being a more specific exception if you should have
handled the no-extras possibility but didn't), but you should feel free
to land as-is.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/canonical/launchpad/scripts/__init__.py'
--- lib/canonical/launchpad/scripts/__init__.py 2011-09-06 07:07:13 +0000
+++ lib/canonical/launchpad/scripts/__init__.py 2011-10-12 20:43:24 +0000
@@ -23,7 +23,6 @@
2323
24from zope.configuration.config import ConfigurationMachine24from zope.configuration.config import ConfigurationMachine
25from zope.security.management import setSecurityPolicy25from zope.security.management import setSecurityPolicy
26from zope.security.simplepolicies import PermissiveSecurityPolicy
27import zope.sendmail.delivery26import zope.sendmail.delivery
28import zope.site.hooks27import zope.site.hooks
2928
@@ -38,7 +37,10 @@
38from canonical.database.postgresql import ConnectionString37from canonical.database.postgresql import ConnectionString
39# Intentional re-export, following along the lines of the logger module.38# Intentional re-export, following along the lines of the logger module.
40from canonical.launchpad.scripts.loghandlers import WatchedFileHandler39from canonical.launchpad.scripts.loghandlers import WatchedFileHandler
41from canonical.launchpad.webapp.authorization import LaunchpadSecurityPolicy40from canonical.launchpad.webapp.authorization import (
41 LaunchpadPermissiveSecurityPolicy,
42 LaunchpadSecurityPolicy,
43 )
42from canonical.launchpad.webapp.interaction import (44from canonical.launchpad.webapp.interaction import (
43 ANONYMOUS,45 ANONYMOUS,
44 setupInteractionByEmail,46 setupInteractionByEmail,
@@ -88,7 +90,7 @@
88 if use_web_security:90 if use_web_security:
89 setSecurityPolicy(LaunchpadSecurityPolicy)91 setSecurityPolicy(LaunchpadSecurityPolicy)
90 else:92 else:
91 setSecurityPolicy(PermissiveSecurityPolicy)93 setSecurityPolicy(LaunchpadPermissiveSecurityPolicy)
9294
93 # Register atexit handler to kill off mail delivery daemon threads, and95 # Register atexit handler to kill off mail delivery daemon threads, and
94 # thus avoid spew at exit. See:96 # thus avoid spew at exit. See:
@@ -109,8 +111,6 @@
109111
110 # This is a convenient hack to set up a zope interaction, before we get112 # This is a convenient hack to set up a zope interaction, before we get
111 # the proper API for having a principal / user running in scripts.113 # the proper API for having a principal / user running in scripts.
112 # The script will have full permissions because of the
113 # PermissiveSecurityPolicy set up in script.zcml.
114 setupInteractionByEmail(ANONYMOUS)114 setupInteractionByEmail(ANONYMOUS)
115115
116116
117117
=== modified file 'lib/canonical/launchpad/webapp/adapter.py'
--- lib/canonical/launchpad/webapp/adapter.py 2011-09-22 02:29:01 +0000
+++ lib/canonical/launchpad/webapp/adapter.py 2011-10-12 20:43:24 +0000
@@ -71,6 +71,7 @@
71 ReadOnlyModeViolation,71 ReadOnlyModeViolation,
72 SLAVE_FLAVOR,72 SLAVE_FLAVOR,
73 )73 )
74from canonical.launchpad.webapp.interaction import get_interaction_extras
74from canonical.launchpad.webapp.opstats import OpStats75from canonical.launchpad.webapp.opstats import OpStats
75from canonical.lazr.timeout import set_default_timeout_function76from canonical.lazr.timeout import set_default_timeout_function
76from lp.services import features77from lp.services import features
@@ -195,7 +196,6 @@
195 _local.enable_timeout = enable_timeout196 _local.enable_timeout = enable_timeout
196 _local.commit_logger = CommitLogger(transaction)197 _local.commit_logger = CommitLogger(transaction)
197 transaction.manager.registerSynch(_local.commit_logger)198 transaction.manager.registerSynch(_local.commit_logger)
198 set_permit_timeout_from_features(False)
199199
200200
201def clear_request_started():201def clear_request_started():
@@ -289,7 +289,7 @@
289 :param enabled: If True permit looking up request timeouts in289 :param enabled: If True permit looking up request timeouts in
290 feature flags.290 feature flags.
291 """291 """
292 _local._permit_feature_timeout = enabled292 get_interaction_extras().permit_timeout_from_features = enabled
293293
294294
295def _get_request_timeout(timeout=None):295def _get_request_timeout(timeout=None):
@@ -302,7 +302,9 @@
302 return None302 return None
303 if timeout is None:303 if timeout is None:
304 timeout = config.database.db_statement_timeout304 timeout = config.database.db_statement_timeout
305 if getattr(_local, '_permit_feature_timeout', False):305 interaction_extras = get_interaction_extras()
306 if (interaction_extras is not None
307 and interaction_extras.permit_timeout_from_features):
306 set_permit_timeout_from_features(False)308 set_permit_timeout_from_features(False)
307 try:309 try:
308 timeout_str = features.getFeatureFlag('hard_timeout')310 timeout_str = features.getFeatureFlag('hard_timeout')
309311
=== modified file 'lib/canonical/launchpad/webapp/authorization.py'
--- lib/canonical/launchpad/webapp/authorization.py 2011-10-12 01:08:48 +0000
+++ lib/canonical/launchpad/webapp/authorization.py 2011-10-12 20:43:24 +0000
@@ -26,10 +26,14 @@
26 checkPermission as check_permission_is_registered,26 checkPermission as check_permission_is_registered,
27 )27 )
28from zope.security.proxy import removeSecurityProxy28from zope.security.proxy import removeSecurityProxy
29from zope.security.simplepolicies import ParanoidSecurityPolicy29from zope.security.simplepolicies import (
30 ParanoidSecurityPolicy,
31 PermissiveSecurityPolicy,
32 )
3033
31from canonical.database.sqlbase import block_implicit_flushes34from canonical.database.sqlbase import block_implicit_flushes
32from canonical.launchpad.readonly import is_read_only35from canonical.launchpad.readonly import is_read_only
36from canonical.launchpad.webapp.interaction import InteractionExtras
33from canonical.launchpad.webapp.interfaces import (37from canonical.launchpad.webapp.interfaces import (
34 AccessLevel,38 AccessLevel,
35 ILaunchpadContainer,39 ILaunchpadContainer,
@@ -47,6 +51,10 @@
47class LaunchpadSecurityPolicy(ParanoidSecurityPolicy):51class LaunchpadSecurityPolicy(ParanoidSecurityPolicy):
48 classProvides(ISecurityPolicy)52 classProvides(ISecurityPolicy)
4953
54 def __init__(self, *participations):
55 ParanoidSecurityPolicy.__init__(self, *participations)
56 self.extras = InteractionExtras()
57
50 def _checkRequiredAccessLevel(self, access_level, permission, object):58 def _checkRequiredAccessLevel(self, access_level, permission, object):
51 """Check that the principal has the level of access required.59 """Check that the principal has the level of access required.
5260
@@ -252,3 +260,10 @@
252 # method, but it is not in an interface, and not implemented by260 # method, but it is not in an interface, and not implemented by
253 # all classes that implement IApplicationRequest.261 # all classes that implement IApplicationRequest.
254 del p.annotations[LAUNCHPAD_SECURITY_POLICY_CACHE_KEY]262 del p.annotations[LAUNCHPAD_SECURITY_POLICY_CACHE_KEY]
263
264
265class LaunchpadPermissiveSecurityPolicy(PermissiveSecurityPolicy):
266
267 def __init__(self, *participations):
268 PermissiveSecurityPolicy.__init__(self, *participations)
269 self.extras = InteractionExtras()
255270
=== modified file 'lib/canonical/launchpad/webapp/ftests/test_adapter.py'
--- lib/canonical/launchpad/webapp/ftests/test_adapter.py 2010-10-04 20:46:55 +0000
+++ lib/canonical/launchpad/webapp/ftests/test_adapter.py 2011-10-12 20:43:24 +0000
@@ -7,23 +7,7 @@
7import unittest7import unittest
88
9from canonical.launchpad.testing.systemdocs import LayeredDocFileSuite9from canonical.launchpad.testing.systemdocs import LayeredDocFileSuite
10from canonical.launchpad.webapp import adapter
11from canonical.testing.layers import LaunchpadFunctionalLayer10from canonical.testing.layers import LaunchpadFunctionalLayer
12from lp.testing import TestCase
13
14
15class TestTimeout(TestCase):
16
17 def test_set_permit_timeout_from_features(self):
18 adapter.set_permit_timeout_from_features(True)
19 self.assertTrue(adapter._local._permit_feature_timeout)
20 adapter.set_permit_timeout_from_features(False)
21 self.assertFalse(adapter._local._permit_feature_timeout)
22
23 def test_set_request_started_disables_flag_timeout(self):
24 adapter.set_request_started()
25 self.addCleanup(adapter.clear_request_started)
26 self.assertFalse(adapter._local._permit_feature_timeout)
2711
2812
29def test_suite():13def test_suite():
3014
=== modified file 'lib/canonical/launchpad/webapp/interaction.py'
--- lib/canonical/launchpad/webapp/interaction.py 2010-08-20 20:31:18 +0000
+++ lib/canonical/launchpad/webapp/interaction.py 2011-10-12 20:43:24 +0000
@@ -47,6 +47,7 @@
4747
48from canonical.launchpad.webapp.interfaces import (48from canonical.launchpad.webapp.interfaces import (
49 IOpenLaunchBag,49 IOpenLaunchBag,
50 IInteractionExtras,
50 IPlacelessAuthUtility,51 IPlacelessAuthUtility,
51 )52 )
5253
@@ -54,10 +55,11 @@
54__all__ = [55__all__ = [
55 'ANONYMOUS',56 'ANONYMOUS',
56 'get_current_principal',57 'get_current_principal',
58 'get_interaction_extras',
57 'setupInteraction',59 'setupInteraction',
58 'setupInteractionByEmail',60 'setupInteractionByEmail',
59 'setupInteractionForPerson',61 'setupInteractionForPerson',
60 'Participation',62 'InteractionExtras',
61 ]63 ]
6264
6365
@@ -171,3 +173,22 @@
171173
172 interaction = None174 interaction = None
173 principal = None175 principal = None
176
177
178class InteractionExtras:
179 """Extra data attached to all interactions. See `IInteractionExtras`."""
180
181 implements(IInteractionExtras)
182 permit_timeout_from_features = False
183
184
185def get_interaction_extras():
186 """Return the active provider of `IInteractionExtras`.
187
188 This is looked up from the interaction. If there is no interaction then
189 return None.
190 """
191 interaction = queryInteraction()
192 if interaction is None:
193 return None
194 return interaction.extras
174195
=== modified file 'lib/canonical/launchpad/webapp/interfaces.py'
--- lib/canonical/launchpad/webapp/interfaces.py 2011-10-03 11:36:55 +0000
+++ lib/canonical/launchpad/webapp/interfaces.py 2011-10-12 20:43:24 +0000
@@ -310,6 +310,25 @@
310 '''310 '''
311311
312312
313class IInteractionExtras(Interface):
314 """We attach a provider of this interface to all interactions.
315
316 Because a fresh provider is constructed for every request and between
317 every test, it is less error-prone to add things to this interface than to
318 stash state on a thread local.
319
320 If you add something here, you should go and edit
321 `canonical.launchpad.webapp.interaction.InteractionExtras`,
322 """
323
324 permit_timeout_from_features = Attribute(
325 """A boolean indicating whether to read the 'hard_timeout' feature
326 flag. We can't check the feature flags early on in request processing
327 because this can trigger nested db lookups. See the docstring of
328 `canonical.launchpad.webapp.servers.set_permit_timeout_from_features`
329 for more.""")
330
331
313#332#
314# Request333# Request
315#334#
316335
=== modified file 'lib/canonical/launchpad/webapp/servers.py'
--- lib/canonical/launchpad/webapp/servers.py 2011-10-03 11:36:55 +0000
+++ lib/canonical/launchpad/webapp/servers.py 2011-10-12 20:43:24 +0000
@@ -866,8 +866,10 @@
866 False866 False
867867
868 """868 """
869 implements(INotificationRequest, IBasicLaunchpadRequest, IParticipation,869 implements(
870 canonical.launchpad.layers.LaunchpadLayer)870 INotificationRequest, IBasicLaunchpadRequest, IParticipation,
871 canonical.launchpad.layers.LaunchpadLayer)
872
871 # These two attributes satisfy IParticipation.873 # These two attributes satisfy IParticipation.
872 principal = None874 principal = None
873 interaction = None875 interaction = None
874876
=== modified file 'lib/canonical/launchpad/webapp/tests/test_servers.py'
--- lib/canonical/launchpad/webapp/tests/test_servers.py 2011-10-03 11:36:55 +0000
+++ lib/canonical/launchpad/webapp/tests/test_servers.py 2011-10-12 20:43:24 +0000
@@ -32,7 +32,9 @@
32 Interface,32 Interface,
33 )33 )
3434
35from canonical.launchpad.webapp.interfaces import IFinishReadOnlyRequestEvent35from canonical.launchpad.webapp.interfaces import (
36 IFinishReadOnlyRequestEvent,
37 )
36from canonical.launchpad.webapp.publication import LaunchpadBrowserPublication38from canonical.launchpad.webapp.publication import LaunchpadBrowserPublication
37from canonical.launchpad.webapp.servers import (39from canonical.launchpad.webapp.servers import (
38 ApplicationServerSettingRequestFactory,40 ApplicationServerSettingRequestFactory,
3941
=== modified file 'lib/canonical/testing/layers.py'
--- lib/canonical/testing/layers.py 2011-10-05 21:33:43 +0000
+++ lib/canonical/testing/layers.py 2011-10-12 20:43:24 +0000
@@ -99,7 +99,6 @@
99 endInteraction,99 endInteraction,
100 getSecurityPolicy,100 getSecurityPolicy,
101 )101 )
102from zope.security.simplepolicies import PermissiveSecurityPolicy
103from zope.server.logger.pythonlogger import PythonLogger102from zope.server.logger.pythonlogger import PythonLogger
104103
105from canonical.config import (104from canonical.config import (
@@ -113,6 +112,9 @@
113 )112 )
114from canonical.database.sqlbase import session_store113from canonical.database.sqlbase import session_store
115from canonical.launchpad.scripts import execute_zcml_for_scripts114from canonical.launchpad.scripts import execute_zcml_for_scripts
115from canonical.launchpad.webapp.authorization import (
116 LaunchpadPermissiveSecurityPolicy,
117 )
116from canonical.launchpad.webapp.interfaces import (118from canonical.launchpad.webapp.interfaces import (
117 DEFAULT_FLAVOR,119 DEFAULT_FLAVOR,
118 IOpenLaunchBag,120 IOpenLaunchBag,
@@ -1209,9 +1211,10 @@
1209 # This should not happen here, it should be caught by the1211 # This should not happen here, it should be caught by the
1210 # testTearDown() method. If it does, something very nasty1212 # testTearDown() method. If it does, something very nasty
1211 # happened.1213 # happened.
1212 if getSecurityPolicy() != PermissiveSecurityPolicy:1214 if getSecurityPolicy() != LaunchpadPermissiveSecurityPolicy:
1213 raise LayerInvariantError(1215 raise LayerInvariantError(
1214 "Previous test removed the PermissiveSecurityPolicy.")1216 "Previous test removed the LaunchpadPermissiveSecurityPolicy."
1217 )
12151218
1216 # execute_zcml_for_scripts() sets up an interaction for the1219 # execute_zcml_for_scripts() sets up an interaction for the
1217 # anonymous user. A previous script may have changed or removed1220 # anonymous user. A previous script may have changed or removed
@@ -1228,10 +1231,10 @@
1228 "Component architecture not loaded or totally screwed")1231 "Component architecture not loaded or totally screwed")
1229 # Make sure that a test that changed the security policy, reset it1232 # Make sure that a test that changed the security policy, reset it
1230 # back to its default value.1233 # back to its default value.
1231 if getSecurityPolicy() != PermissiveSecurityPolicy:1234 if getSecurityPolicy() != LaunchpadPermissiveSecurityPolicy:
1232 raise LayerInvariantError(1235 raise LayerInvariantError(
1233 "This test removed the PermissiveSecurityPolicy and didn't "1236 "This test removed the LaunchpadPermissiveSecurityPolicy and "
1234 "restore it.")1237 "didn't restore it.")
1235 logout()1238 logout()
12361239
12371240
12381241
=== renamed file 'lib/lp/bugs/doc/bugtracker-tokens.txt.disabled' => 'lib/lp/bugs/doc/bugtracker-tokens.txt'
=== modified file 'lib/lp/code/tests/test_doc.py'
--- lib/lp/code/tests/test_doc.py 2011-08-12 19:15:43 +0000
+++ lib/lp/code/tests/test_doc.py 2011-10-12 20:43:24 +0000
@@ -38,7 +38,7 @@
3838
39 To be able to use LaunchpadZopelessLayer.switchDbUser in a test, we need39 To be able to use LaunchpadZopelessLayer.switchDbUser in a test, we need
40 to run in the Zopeless environment. The Zopeless environment normally runs40 to run in the Zopeless environment. The Zopeless environment normally runs
41 using the PermissiveSecurityPolicy. If we want the test to cover41 using the LaunchpadPermissiveSecurityPolicy. If we want the test to cover
42 functionality used in the webapp, it needs to use the42 functionality used in the webapp, it needs to use the
43 LaunchpadSecurityPolicy.43 LaunchpadSecurityPolicy.
44 """44 """
4545
=== modified file 'lib/lp/testing/__init__.py'
--- lib/lp/testing/__init__.py 2011-10-05 21:46:17 +0000
+++ lib/lp/testing/__init__.py 2011-10-12 20:43:24 +0000
@@ -115,7 +115,6 @@
115 )115 )
116from canonical.launchpad.webapp.adapter import (116from canonical.launchpad.webapp.adapter import (
117 print_queries,117 print_queries,
118 set_permit_timeout_from_features,
119 start_sql_logging,118 start_sql_logging,
120 stop_sql_logging,119 stop_sql_logging,
121 )120 )
@@ -579,7 +578,6 @@
579 self.addCleanup(578 self.addCleanup(
580 self.attachLibrarianLog,579 self.attachLibrarianLog,
581 LibrarianLayer.librarian_fixture)580 LibrarianLayer.librarian_fixture)
582 set_permit_timeout_from_features(False)
583581
584 @adapter(ErrorReportEvent)582 @adapter(ErrorReportEvent)
585 def _recordOops(self, event):583 def _recordOops(self, event):