Merge lp:~flacoste/launchpad/bug-559128 into lp:launchpad

Proposed by Francis J. Lacoste
Status: Merged
Approved by: Gary Poster
Approved revision: no longer in the source branch.
Merged at revision: not available
Proposed branch: lp:~flacoste/launchpad/bug-559128
Merge into: lp:launchpad
Diff against target: 452 lines (+121/-96)
10 files modified
lib/canonical/launchpad/scripts/__init__.py (+16/-18)
lib/canonical/launchpad/webapp/interaction.py (+62/-1)
lib/lp/bugs/scripts/checkwatches/updater.py (+3/-2)
lib/lp/code/xmlrpc/codehosting.py (+4/-8)
lib/lp/services/scripts/base.py (+3/-13)
lib/lp/testing/__init__.py (+2/-1)
lib/lp/testing/_login.py (+25/-38)
lib/lp/testing/_webservice.py (+2/-1)
scripts/bugzilla-import.py (+2/-7)
scripts/sourceforge-import.py (+2/-7)
To merge this branch: bzr merge lp:~flacoste/launchpad/bug-559128
Reviewer Review Type Date Requested Status
Gary Poster (community) Approve
Review via email: mp+23504@code.launchpad.net

Commit message

Don't import lp.testing in production code. Refactor login and login_person helper into setupInteractionByEmail and setupInteractionForPerson that can be used in production code.

Description of the change

= Summary =

This branch should re-enable edge update (bug #559128) by fixing some tech-debt
(bug #285808)

The problem with the edge update is that subunit is now installed via a
package and that package isn't installed in production. You'd wonder why
subunit would be required for running Launchpad and that's exactly the point.

It turns out that some production code paths import from lp.testing because
they use the login and login_person helper (which was bug #285808).

== Proposed fix ==

Remove tech-debts

== Pre-implementation notes ==

Nothing special.

== Implementation details ==

I moved the useful part of login and login_person into two functions
setupInteractionByEmail and setupInteractionForPerson. Those lives alongside
setupInteraction in canonical.launchpad.webapp.interaction.

The login and login_person() contains the test-specific logic around these.

I updated all production call sites to use the one from
canonical.launchpad.webapp.interaction

Since execute_zcml_for_scripts also imported testing code, i wrapped that one
only if the layers module has been imported. I would have removed it entirely,
but thought that the safety hook was worth the relative ugliness.

== Tests ==

This branch is a pure refactoring. I did test that lp.testing wasn't imported
anymore in production paths by adding a raise RuntimeError in lp.testing, it's
not trigger when calling make run. (It is before this fix.)

== Demo and Q/A ==

Nothing special

= Launchpad lint =

Checking for conflicts. and issues in doctests and templates.
Running jslint, xmllint, pyflakes, and pylint.
Using normal rules.

Linting changed files:
  lib/canonical/launchpad/scripts/__init__.py
  lib/lp/services/scripts/base.py
  scripts/sourceforge-import.py
  lib/lp/code/xmlrpc/codehosting.py
  lib/lp/bugs/scripts/checkwatches/updater.py
  lib/lp/testing/__init__.py
  lib/canonical/launchpad/webapp/interaction.py
  scripts/bugzilla-import.py
  lib/lp/testing/_webservice.py
  lib/lp/testing/_login.py

== Pyflakes notices ==

lib/lp/testing/_login.py
    8: 'getUtility' imported but unused

I fixed that one on a follow-up commit.

--
Francis J. Lacoste
<email address hidden>

To post a comment you must log in.
Revision history for this message
Gary Poster (gary) wrote :

Wow, very nice!

"Zopefull": nice word :-)

Very nice cleanups in the branch, such as correcting the imports from zope.security.

A niggle, but I found it a bit odd when ``setupInteractionForPerson`` called ``return setupInteractionByEmail(ANONYMOUS, participation)``. I wondered why I should call a function with the word "email" in it to get an interaction when there's no email involved. My preference would be to change setupInteraction to look like this:

def setupInteraction(principal, login=None, participation=None):
    """Sets up a new interaction with the given principal.

    The login gets added to the launch bag.

    You can optionally pass in a participation to be used. If no
    participation is given, a Participation is used.
    """
    # If principal is None, this method acts just like endInteraction.
    if principal is None:
        endInteraction()
        return

    # THIS IS THE NEW BIT
    if principal == ANONYMOUS:
        authutil = getUtility(IPlacelessAuthUtility)
        principal = authutil.unauthenticatedPrincipal()

    if participation is None:
        participation = Participation()
(... and so on, as is)

Then the line in `setupInteractionForPerson`` would read ``return setupInteraction(ANONYMOUS)``. That makes much more sense to me. I'd guess you'd also delete these lines from ``setupInteractionByEmail`` too, because they would be unnecessary:

119 + else:
120 + principal = authutil.unauthenticatedPrincipal()

As I said, that's a niggle, and I won't insist on it, but it did give me pause.

Looks like you caught all my XXXs. :-) Yay!

Thank you,

Gary

review: Approve
Revision history for this message
Francis J. Lacoste (flacoste) wrote :

On April 15, 2010, Gary Poster wrote:
> A niggle, but I found it a bit odd when ``setupInteractionForPerson``
> called ``return setupInteractionByEmail(ANONYMOUS, participation)``. I
> wondered why I should call a function with the word "email" in it to get
> an interaction when there's no email involved. My preference would be to
> change setupInteraction to look like this:
>
Well, I guess, I could call setupInteraction directly in that case. I'll do
this.

> def setupInteraction(principal, login=None, participation=None):
> """Sets up a new interaction with the given principal.

This changes the signature of the function. I'll pass on it since I don't feel
like chasing all the call sites :-)

Cheers

--
Francis J. Lacoste
<email address hidden>

Revision history for this message
Francis J. Lacoste (flacoste) wrote :

On April 15, 2010, Francis J. Lacoste wrote:
> On April 15, 2010, Gary Poster wrote:
> > A niggle, but I found it a bit odd when ``setupInteractionForPerson``
> > called ``return setupInteractionByEmail(ANONYMOUS, participation)``. I
> > wondered why I should call a function with the word "email" in it to get
> > an interaction when there's no email involved. My preference would be to
>
> > change setupInteraction to look like this:
> Well, I guess, I could call setupInteraction directly in that case. I'll do
> this.
>
> > def setupInteraction(principal, login=None, participation=None):
> > """Sets up a new interaction with the given principal.
>
> This changes the signature of the function. I'll pass on it since I don't
> feel like chasing all the call sites :-)
>
> Cheers

Disregard this, your suggestion makes perfect sense and I'll implement it.

/me shouldn't reply before the context restore has finished...

--
Francis J. Lacoste
<email address hidden>

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 2010-04-09 12:31:20 +0000
+++ lib/canonical/launchpad/scripts/__init__.py 2010-04-17 00:32:28 +0000
@@ -20,6 +20,7 @@
2020
21import atexit21import atexit
22import os22import os
23import sys
23from textwrap import dedent24from textwrap import dedent
24import threading25import threading
2526
@@ -32,6 +33,8 @@
32from zope.security.simplepolicies import PermissiveSecurityPolicy33from zope.security.simplepolicies import PermissiveSecurityPolicy
3334
34from canonical.launchpad.webapp.authorization import LaunchpadSecurityPolicy35from canonical.launchpad.webapp.authorization import LaunchpadSecurityPolicy
36from canonical.launchpad.webapp.interaction import (
37 ANONYMOUS, setupInteractionByEmail)
3538
36from canonical import lp39from canonical import lp
37from canonical.config import config40from canonical.config import config
@@ -91,15 +94,18 @@
91 application uses will be used. Otherwise everything protected by a94 application uses will be used. Otherwise everything protected by a
92 permission is allowed, and everything else denied.95 permission is allowed, and everything else denied.
93 """96 """
94 # Prevent some cases of erroneous layer useage.97
95 from canonical.testing import (98 # When in testing mode, prevent some cases of erroneous layer usage.
96 FunctionalLayer, BaseLayer, ZopelessLayer99 # But we don't want to import that module in production usage, thus
97 )100 # the conditional block.
98 assert not FunctionalLayer.isSetUp, \101 if 'canonical.testing.layers' in sys.modules:
99 'Setting up Zopeless CA when Zopefull CA is already running'102 from canonical.testing.layers import (
100 assert not BaseLayer.isSetUp or ZopelessLayer.isSetUp, """103 FunctionalLayer, BaseLayer, ZopelessLayer)
101 execute_zcml_for_scripts should not be called from tests.104 assert not FunctionalLayer.isSetUp, \
102 Instead, your test should use the Zopeless layer.105 'Setting up Zopeless CA when Zopefull CA is already running'
106 assert not BaseLayer.isSetUp or ZopelessLayer.isSetUp, """
107 execute_zcml_for_scripts should not be called from tests.
108 Instead, your test should use the Zopeless layer.
103 """109 """
104110
105 if config.instance_name == 'testrunner':111 if config.instance_name == 'testrunner':
@@ -147,15 +153,7 @@
147 # the proper API for having a principal / user running in scripts.153 # the proper API for having a principal / user running in scripts.
148 # The script will have full permissions because of the154 # The script will have full permissions because of the
149 # PermissiveSecurityPolicy set up in script.zcml.155 # PermissiveSecurityPolicy set up in script.zcml.
150 # XXX gary 20-Oct-2008 bug 285808156 setupInteractionByEmail(ANONYMOUS)
151 # The wisdom of using a test fixture for production should be
152 # reconsidered.
153 from canonical.launchpad.ftests import login
154 # The Participation is used to specify that we do not want a
155 # LaunchpadTestRequest, which ftests normally use. shipit scripts, in
156 # particular, need to be careful, because of code in canonical_url.
157 from canonical.launchpad.webapp.interaction import Participation
158 login('launchpad.anonymous', Participation())
159157
160158
161def db_options(parser):159def db_options(parser):
162160
=== modified file 'lib/canonical/launchpad/webapp/interaction.py'
--- lib/canonical/launchpad/webapp/interaction.py 2009-06-25 05:30:52 +0000
+++ lib/canonical/launchpad/webapp/interaction.py 2010-04-17 00:32:28 +0000
@@ -13,7 +13,20 @@
13from zope.security.management import (13from zope.security.management import (
14 endInteraction, newInteraction, queryInteraction)14 endInteraction, newInteraction, queryInteraction)
1515
16from canonical.launchpad.webapp.interfaces import IOpenLaunchBag16from canonical.launchpad.webapp.interfaces import (
17 IOpenLaunchBag, IPlacelessAuthUtility)
18
19
20__all__ = [
21 'ANONYMOUS',
22 'get_current_principal',
23 'setupInteraction',
24 'setupInteractionByEmail',
25 'setupInteractionForPerson',
26 ]
27
28
29ANONYMOUS = 'launchpad.anonymous'
1730
1831
19def get_current_principal():32def get_current_principal():
@@ -40,6 +53,10 @@
40 endInteraction()53 endInteraction()
41 return54 return
4255
56 if principal == ANONYMOUS:
57 authutil = getUtility(IPlacelessAuthUtility)
58 principal = authutil.unauthenticatedPrincipal()
59
43 if participation is None:60 if participation is None:
44 participation = Participation()61 participation = Participation()
4562
@@ -61,7 +78,51 @@
61 participation.principal = principal78 participation.principal = principal
6279
6380
81def setupInteractionByEmail(email, participation=None):
82 """Setup an interaction using an email.
83
84 If the ANONYMOUS constant is supplied as the email,
85 an interaction for the anonymous user will be used.
86
87 You can optionally pass in a participation to be used. If no
88 participation is given, an empty participation is used.
89
90 If the participation provides IPublicationRequest, it must implement
91 setPrincipal(), otherwise it must allow setting its principal attribute.
92 """
93 authutil = getUtility(IPlacelessAuthUtility)
94
95 if email != ANONYMOUS:
96 # Create an anonymous interaction first because this calls
97 # IPersonSet.getByEmail() and since this is security wrapped, it needs
98 # an interaction available.
99 setupInteraction(authutil.unauthenticatedPrincipal())
100 principal = authutil.getPrincipalByLogin(email, want_password=False)
101 assert principal is not None, "Invalid login"
102 if principal.person is not None and principal.person.is_team:
103 raise AssertionError("Please do not try to login as a team")
104 else:
105 principal = authutil.unauthenticatedPrincipal()
106
107 if participation is None:
108 participation = Participation()
109
110 setupInteraction(principal, login=email, participation=participation)
111
112
113def setupInteractionForPerson(person, participation=None):
114 """Setup a participation for a person."""
115 from zope.security.proxy import removeSecurityProxy
116 if person is None:
117 return setupInteraction(ANONYMOUS, participation)
118 else:
119 # Bypass zope's security because IEmailAddress.email is not public.
120 naked_email = removeSecurityProxy(person.preferredemail)
121 return setupInteractionByEmail(naked_email.email, participation)
122
123
64class Participation:124class Participation:
125 """A very simple participation."""
65 implements(IParticipation)126 implements(IParticipation)
66127
67 interaction = None128 interaction = None
68129
=== modified file 'lib/lp/bugs/scripts/checkwatches/updater.py'
--- lib/lp/bugs/scripts/checkwatches/updater.py 2010-04-12 16:06:11 +0000
+++ lib/lp/bugs/scripts/checkwatches/updater.py 2010-04-17 00:32:28 +0000
@@ -37,6 +37,8 @@
3737
38from zope.component import getUtility38from zope.component import getUtility
39from zope.event import notify39from zope.event import notify
40from zope.security.management import (
41 endInteraction, queryInteraction)
4042
41from canonical.database.constants import UTC_NOW43from canonical.database.constants import UTC_NOW
42from canonical.database.sqlbase import flush_database_updates44from canonical.database.sqlbase import flush_database_updates
@@ -54,9 +56,8 @@
54 clear_request_started, get_request_start_time, set_request_started)56 clear_request_started, get_request_start_time, set_request_started)
55from canonical.launchpad.webapp.errorlog import (57from canonical.launchpad.webapp.errorlog import (
56 ErrorReportingUtility, ScriptRequest)58 ErrorReportingUtility, ScriptRequest)
59from canonical.launchpad.webapp.interaction import setupInteraction
57from canonical.launchpad.webapp.interfaces import IPlacelessAuthUtility60from canonical.launchpad.webapp.interfaces import IPlacelessAuthUtility
58from canonical.launchpad.webapp.interaction import (
59 setupInteraction, endInteraction, queryInteraction)
60from canonical.launchpad.webapp.publisher import canonical_url61from canonical.launchpad.webapp.publisher import canonical_url
6162
62from lp.bugs import externalbugtracker63from lp.bugs import externalbugtracker
6364
=== modified file 'lib/lp/code/xmlrpc/codehosting.py'
--- lib/lp/code/xmlrpc/codehosting.py 2010-02-24 04:24:01 +0000
+++ lib/lp/code/xmlrpc/codehosting.py 2010-04-17 00:32:28 +0000
@@ -21,8 +21,8 @@
21from zope.interface import implements21from zope.interface import implements
22from zope.security.interfaces import Unauthorized22from zope.security.interfaces import Unauthorized
23from zope.security.proxy import removeSecurityProxy23from zope.security.proxy import removeSecurityProxy
24from zope.security.management import endInteraction
2425
25from canonical.launchpad.ftests import login_person, logout
26from lp.code.errors import UnknownBranchTypeError26from lp.code.errors import UnknownBranchTypeError
27from lp.code.enums import BranchType27from lp.code.enums import BranchType
28from lp.code.interfaces.branch import BranchCreationException28from lp.code.interfaces.branch import BranchCreationException
@@ -40,11 +40,11 @@
40from canonical.launchpad.validators import LaunchpadValidationError40from canonical.launchpad.validators import LaunchpadValidationError
41from canonical.launchpad.webapp import LaunchpadXMLRPCView41from canonical.launchpad.webapp import LaunchpadXMLRPCView
42from canonical.launchpad.webapp.authorization import check_permission42from canonical.launchpad.webapp.authorization import check_permission
43from canonical.launchpad.webapp.interaction import setupInteractionForPerson
43from canonical.launchpad.webapp.interfaces import (44from canonical.launchpad.webapp.interfaces import (
44 NameLookupFailed, NotFoundError)45 NameLookupFailed, NotFoundError)
45from canonical.launchpad.xmlrpc import faults46from canonical.launchpad.xmlrpc import faults
46from canonical.launchpad.xmlrpc.helpers import return_fault47from canonical.launchpad.xmlrpc.helpers import return_fault
47from canonical.launchpad.webapp.interaction import Participation
4848
4949
50UTC = pytz.timezone('UTC')50UTC = pytz.timezone('UTC')
@@ -179,15 +179,11 @@
179 requester = getUtility(IPersonSet).get(login_id)179 requester = getUtility(IPersonSet).get(login_id)
180 if requester is None:180 if requester is None:
181 raise NotFoundError("No person with id %s." % login_id)181 raise NotFoundError("No person with id %s." % login_id)
182 # XXX gary 21-Oct-2008 bug 285808182 setupInteractionForPerson(requester)
183 # We should reconsider using a ftest helper for production code. For now,
184 # we explicitly keep the code from using a test request by using a basic
185 # participation.
186 login_person(requester, Participation())
187 try:183 try:
188 return function(requester, *args, **kwargs)184 return function(requester, *args, **kwargs)
189 finally:185 finally:
190 logout()186 endInteraction()
191187
192188
193class BranchFileSystem(LaunchpadXMLRPCView):189class BranchFileSystem(LaunchpadXMLRPCView):
194190
=== modified file 'lib/lp/services/scripts/base.py'
--- lib/lp/services/scripts/base.py 2009-09-21 08:13:40 +0000
+++ lib/lp/services/scripts/base.py 2010-04-17 00:32:28 +0000
@@ -23,8 +23,9 @@
23from canonical.database.sqlbase import ISOLATION_LEVEL_DEFAULT23from canonical.database.sqlbase import ISOLATION_LEVEL_DEFAULT
24from canonical.launchpad import scripts24from canonical.launchpad import scripts
25from canonical.launchpad.interfaces import IScriptActivitySet25from canonical.launchpad.interfaces import IScriptActivitySet
26from canonical.launchpad.webapp.interaction import (
27 ANONYMOUS, setupInteractionByEmail)
26from canonical.lp import initZopeless28from canonical.lp import initZopeless
27from lp.testing import ANONYMOUS
2829
2930
30LOCK_PATH = "/var/lock/"31LOCK_PATH = "/var/lock/"
@@ -159,18 +160,7 @@
159160
160 def login(self, user):161 def login(self, user):
161 """Super-convenience method that avoids the import."""162 """Super-convenience method that avoids the import."""
162 # This import is actually quite expensive, and causes us to163 setupInteractionByEmail(user)
163 # import circularly in pathological cases.
164 # XXX gary 20-Oct-2008 bug 285808
165 # The wisdom of using a test fixture for production should be
166 # reconsidered.
167 from canonical.launchpad.ftests import login
168 # The Participation is used to specify that we do not want a
169 # LaunchpadTestRequest, which ftests normally use. shipit scripts,
170 # in particular, need to be careful, because of code in
171 # canonical_url.
172 from canonical.launchpad.webapp.interaction import Participation
173 login(user, Participation())
174164
175 #165 #
176 # Locking and running methods. Users only call these explicitly if166 # Locking and running methods. Users only call these explicitly if
177167
=== modified file 'lib/lp/testing/__init__.py'
--- lib/lp/testing/__init__.py 2010-04-15 14:38:43 +0000
+++ lib/lp/testing/__init__.py 2010-04-17 00:32:28 +0000
@@ -74,13 +74,14 @@
7474
75from canonical.launchpad.webapp import errorlog75from canonical.launchpad.webapp import errorlog
76from canonical.config import config76from canonical.config import config
77from canonical.launchpad.webapp.interaction import ANONYMOUS
77from canonical.launchpad.webapp.interfaces import ILaunchBag78from canonical.launchpad.webapp.interfaces import ILaunchBag
78from canonical.launchpad.windmill.testing import constants79from canonical.launchpad.windmill.testing import constants
79from lp.codehosting.vfs import branch_id_to_path, get_multi_server80from lp.codehosting.vfs import branch_id_to_path, get_multi_server
80# Import the login and logout functions here as it is a much better81# Import the login and logout functions here as it is a much better
81# place to import them from in tests.82# place to import them from in tests.
82from lp.testing._login import (83from lp.testing._login import (
83 ANONYMOUS, is_logged_in, login, login_person, logout)84 is_logged_in, login, login_person, logout)
84# canonical.launchpad.ftests expects test_tales to be imported from here.85# canonical.launchpad.ftests expects test_tales to be imported from here.
85# XXX: JonathanLange 2010-01-01: Why?!86# XXX: JonathanLange 2010-01-01: Why?!
86from lp.testing._tales import test_tales87from lp.testing._tales import test_tales
8788
=== modified file 'lib/lp/testing/_login.py'
--- lib/lp/testing/_login.py 2009-06-25 04:06:00 +0000
+++ lib/lp/testing/_login.py 2010-04-17 00:32:28 +0000
@@ -5,10 +5,9 @@
5# pylint: disable-msg=W0602,W06035# pylint: disable-msg=W0602,W0603
6__metaclass__ = type6__metaclass__ = type
77
8from zope.component import getUtility
9from zope.security.management import endInteraction8from zope.security.management import endInteraction
10from canonical.launchpad.webapp.interfaces import IPlacelessAuthUtility9from canonical.launchpad.webapp.interaction import (
11from canonical.launchpad.webapp.interaction import setupInteraction10 setupInteractionByEmail, setupInteractionForPerson)
12from canonical.launchpad.webapp.servers import LaunchpadTestRequest11from canonical.launchpad.webapp.servers import LaunchpadTestRequest
13from canonical.launchpad.webapp.vhosts import allvhosts12from canonical.launchpad.webapp.vhosts import allvhosts
1413
@@ -16,18 +15,33 @@
16 'login',15 'login',
17 'login_person',16 'login_person',
18 'logout',17 'logout',
19 'ANONYMOUS',
20 'is_logged_in']18 'is_logged_in']
2119
2220
23ANONYMOUS = 'launchpad.anonymous'
24
25_logged_in = False21_logged_in = False
2622
27def is_logged_in():23def is_logged_in():
28 global _logged_in24 global _logged_in
29 return _logged_in25 return _logged_in
3026
27
28def _test_login_impl(participation):
29 # Common implementation of the test login wrappers.
30 # It sets the global _logged_in flag and create a default
31 # participation if None was specified.
32 global _logged_in
33 _logged_in = True
34
35 if participation is None:
36 # we use the main site as the host name. This is a guess, to make
37 # canonical_url produce a real-looking host name rather than
38 # 127.0.0.1.
39 participation = LaunchpadTestRequest(
40 environ={'HTTP_HOST': allvhosts.configs['mainsite'].hostname,
41 'SERVER_URL': allvhosts.configs['mainsite'].rooturl})
42 return participation
43
44
31def login(email, participation=None):45def login(email, participation=None):
32 """Simulates a login, using the specified email.46 """Simulates a login, using the specified email.
3347
@@ -40,42 +54,15 @@
40 If the participation provides IPublicationRequest, it must implement54 If the participation provides IPublicationRequest, it must implement
41 setPrincipal(), otherwise it must allow setting its principal attribute.55 setPrincipal(), otherwise it must allow setting its principal attribute.
42 """56 """
43 global _logged_in57
44 _logged_in = True58 participation = _test_login_impl(participation)
45 authutil = getUtility(IPlacelessAuthUtility)59 setupInteractionByEmail(email, participation)
46
47 if email != ANONYMOUS:
48 # Create an anonymous interaction first because this calls
49 # IPersonSet.getByEmail() and since this is security wrapped, it needs
50 # an interaction available.
51 setupInteraction(authutil.unauthenticatedPrincipal())
52 principal = authutil.getPrincipalByLogin(email, want_password=False)
53 assert principal is not None, "Invalid login"
54 if principal.person is not None and principal.person.is_team:
55 raise AssertionError("Please do not try to login as a team")
56 else:
57 principal = authutil.unauthenticatedPrincipal()
58
59 if participation is None:
60 # we use the main site as the host name. This is a guess, to make
61 # canonical_url produce a real-looking host name rather than
62 # 127.0.0.1.
63 participation = LaunchpadTestRequest(
64 environ={'HTTP_HOST': allvhosts.configs['mainsite'].hostname,
65 'SERVER_URL': allvhosts.configs['mainsite'].rooturl})
66
67 setupInteraction(principal, login=email, participation=participation)
6860
6961
70def login_person(person, participation=None):62def login_person(person, participation=None):
71 """Login the person with their preferred email."""63 """Login the person with their preferred email."""
72 from zope.security.proxy import removeSecurityProxy64 participation = _test_login_impl(participation)
73 if person is None:65 setupInteractionForPerson(person, participation)
74 return login(ANONYMOUS, participation)
75 else:
76 # Bypass zope's security because IEmailAddress.email is not public.
77 naked_email = removeSecurityProxy(person.preferredemail)
78 return login(naked_email.email, participation)
7966
8067
81def logout():68def logout():
8269
=== modified file 'lib/lp/testing/_webservice.py'
--- lib/lp/testing/_webservice.py 2010-03-30 09:18:53 +0000
+++ lib/lp/testing/_webservice.py 2010-04-17 00:32:28 +0000
@@ -15,11 +15,12 @@
15from launchpadlib.credentials import AccessToken, Credentials15from launchpadlib.credentials import AccessToken, Credentials
16from launchpadlib.launchpad import Launchpad16from launchpadlib.launchpad import Launchpad
1717
18from canonical.launchpad.webapp.interaction import ANONYMOUS
18from canonical.launchpad.webapp.interfaces import OAuthPermission19from canonical.launchpad.webapp.interfaces import OAuthPermission
19from canonical.launchpad.interfaces import (20from canonical.launchpad.interfaces import (
20 IOAuthConsumerSet, IPersonSet)21 IOAuthConsumerSet, IPersonSet)
2122
22from lp.testing._login import ANONYMOUS, login, logout23from lp.testing._login import login, logout
2324
24def oauth_access_token_for(consumer_name, person, permission, context=None):25def oauth_access_token_for(consumer_name, person, permission, context=None):
25 """Find or create an OAuth access token for the given person.26 """Find or create an OAuth access token for the given person.
2627
=== modified file 'scripts/bugzilla-import.py'
--- scripts/bugzilla-import.py 2010-02-16 15:25:52 +0000
+++ scripts/bugzilla-import.py 2010-04-17 00:32:28 +0000
@@ -15,8 +15,7 @@
15from canonical.lp import initZopeless15from canonical.lp import initZopeless
16from canonical.launchpad.scripts import (16from canonical.launchpad.scripts import (
17 execute_zcml_for_scripts, logger_options, logger)17 execute_zcml_for_scripts, logger_options, logger)
18from canonical.launchpad.ftests import login18from canonical.launchpad.webapp.interaction import setupInteractionByEmail
19from canonical.launchpad.webapp.interaction import Participation
2019
21from canonical.launchpad.scripts import bugzilla20from canonical.launchpad.scripts import bugzilla
2221
@@ -81,11 +80,7 @@
8180
82 execute_zcml_for_scripts()81 execute_zcml_for_scripts()
83 ztm = initZopeless()82 ztm = initZopeless()
84 # XXX gary 21-Oct-2008 bug 28580883 setupInteractionByEmail('bug-importer@launchpad.net')
85 # We should reconsider using a ftest helper for production code. For now,
86 # we explicitly keep the code from using a test request by using a basic
87 # participation.
88 login('bug-importer@launchpad.net', Participation())
8984
90 db = make_connection(options)85 db = make_connection(options)
91 bz = bugzilla.Bugzilla(db)86 bz = bugzilla.Bugzilla(db)
9287
=== modified file 'scripts/sourceforge-import.py'
--- scripts/sourceforge-import.py 2010-02-16 15:25:52 +0000
+++ scripts/sourceforge-import.py 2010-04-17 00:32:28 +0000
@@ -16,8 +16,7 @@
16from canonical.launchpad.interfaces import IProductSet16from canonical.launchpad.interfaces import IProductSet
17from canonical.launchpad.scripts import (17from canonical.launchpad.scripts import (
18 execute_zcml_for_scripts, logger_options, logger)18 execute_zcml_for_scripts, logger_options, logger)
19from canonical.launchpad.ftests import login19from canonical.launchpad.webapp.interaction import setupInteractionByEmail
20from canonical.launchpad.webapp.interaction import Participation
2120
22from canonical.launchpad.scripts.sftracker import Tracker, TrackerImporter21from canonical.launchpad.scripts.sftracker import Tracker, TrackerImporter
2322
@@ -52,11 +51,7 @@
5251
53 execute_zcml_for_scripts()52 execute_zcml_for_scripts()
54 ztm = initZopeless()53 ztm = initZopeless()
55 # XXX gary 21-Oct-2008 bug 28580854 setupInteractionByEmail('bug-importer@launchpad.net')
56 # We should reconsider using a ftest helper for production code. For now,
57 # we explicitly keep the code from using a test request by using a basic
58 # participation.
59 login('bug-importer@launchpad.net', Participation())
6055
61 product = getUtility(IProductSet).getByName(options.product)56 product = getUtility(IProductSet).getByName(options.product)
62 tracker = Tracker(options.dumpfile, options.dumpdir)57 tracker = Tracker(options.dumpfile, options.dumpdir)