Merge ~cjwatson/launchpad:modern-ztk into launchpad:master

Proposed by Colin Watson on 2019-12-13
Status: Merged
Approved by: Colin Watson on 2019-12-16
Approved revision: ecf2fd6f9603113f5a58cb7bcd3b6da48947e8ff
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~cjwatson/launchpad:modern-ztk
Merge into: launchpad:master
Diff against target: 743 lines (+196/-212)
18 files modified
constraints.txt (+155/-196)
lib/lp/app/browser/launchpadform.py (+12/-1)
lib/lp/app/doc/tales.txt (+1/-1)
lib/lp/app/stories/basics/xx-lowercase-redirection.txt (+1/-1)
lib/lp/bugs/stories/webservice/xx-bug-target.txt (+1/-1)
lib/lp/registry/browser/distributionmirror.py (+1/-0)
lib/lp/registry/browser/poll.py (+1/-0)
lib/lp/registry/browser/team.py (+1/-0)
lib/lp/scripts/helpers.py (+1/-1)
lib/lp/services/messaging/tests/test_rabbit.py (+1/-1)
lib/lp/services/verification/browser/logintoken.py (+1/-0)
lib/lp/services/webapp/doc/test_adapter.txt (+1/-1)
lib/lp/services/webapp/doc/webapp-authorization.txt (+1/-1)
lib/lp/services/webapp/doc/webapp-publication.txt (+2/-2)
lib/lp/services/webapp/publication.py (+6/-1)
lib/lp/services/webapp/session.py (+2/-3)
lib/lp/translations/browser/language.py (+1/-0)
setup.py (+7/-2)
Reviewer Review Type Date Requested Status
William Grant code 2019-12-13 Approve on 2019-12-16
Review via email: mp+376781@code.launchpad.net

Commit message

Upgrade ZTK packages to 2019-10-23 versions

Description of the change

We now maintain a branch of zope.session rather than freezing it at an old version, and we now track zope.app.* packages individually rather than via the long-gone zopeapp-versions.cfg.

A few things needed to change at the same time as this upgrade:

 * The signature of zope.formlib.form.checkInvariants changed to allow checking form invariants against contexts other than the form itself. For most of our forms this is reasonable, but it isn't suitable for a few of them, notably those that create new objects. To allow for that, I added a new LaunchpadFormView.invariant_context attribute, defaulting to the view's context but customisable by individual views.

 * transaction 2.0.1 removes ITransaction.setUser and places stricter requirements on ITransaction.user. Adjust for this.

 * We poke inside the implementation of transaction managers in a couple of places, and for those we need to adjust for the ThreadTransactionManager implementation change in transaction 2.4.0.

 * I upgraded launchpadlib to weaken its hosted-files test, which would otherwise fail with zope.publisher >= 4.2.2.

 * I weakened a test in xx-bug-target.txt due to changes in zope.schema 4.6.0, as described in https://github.com/zopefoundation/zope.schema/pull/85. This isn't entirely ideal, but we can live with the error messages here being a bit ugly until we come up with something better.

 * A few minor details of things like rendering and exception arguments changed.

The new dependencies are in https://code.launchpad.net/~cjwatson/lp-source-dependencies/+git/lp-source-dependencies/+merge/376770.

To post a comment you must log in.
William Grant (wgrant) wrote :

Nicely done, just one thing...

review: Approve (code)
~cjwatson/launchpad:modern-ztk updated on 2019-12-16
ecf2fd6... by Colin Watson on 2019-12-16

Document odd txn.user syntax

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/constraints.txt b/constraints.txt
2index 94b80d3..a4985d1 100644
3--- a/constraints.txt
4+++ b/constraints.txt
5@@ -1,197 +1,162 @@
6-# ztk-versions.cfg from ZTK 1.1.6, with some upgrades
7-# ---------------------------------------------------
8+# ztk-versions.cfg from ZTK a9eb2093b5 (2019-10-23), with some upgrades
9+# ---------------------------------------------------------------------
10
11-zope.annotation==3.6.0
12-zope.applicationcontrol==3.5.5
13-zope.authentication==3.7.1
14-zope.broken==3.6.0
15-zope.browser==1.3
16-zope.browsermenu==3.9.1
17-zope.browserpage==3.12.2
18-zope.browserresource==3.12.0
19-zope.cachedescriptors==3.5.1
20-zope.catalog==3.8.2
21-#zope.component==3.10.0
22+zope.annotation==4.7.0
23+zope.applicationcontrol==4.2.0
24+zope.authentication==4.4.0
25+zope.browser==2.3
26+zope.browsermenu==4.4
27+zope.browserpage==4.3.0
28+zope.browserresource==4.3
29+zope.cachedescriptors==4.3.1
30+zope.catalog==4.2.1
31 # Tell pip about extras to work around https://github.com/pypa/pip/issues/3046
32 # XXX cjwatson 2017-09-03: This should be fixed in pip 9.0.0, but apparently
33 # isn't.
34-# Upgrade from ZTK 1.1.6 for ZCML registration performance.
35-zope.component[hook,zcml]==3.11.0
36-zope.componentvocabulary==1.0.1
37-zope.configuration==3.7.4
38-zope.container==3.12.0
39-zope.contentprovider==3.7.2
40-zope.contenttype==3.5.5
41-zope.copy==3.5.0
42-zope.copypastemove==3.8.0
43-zope.datetime==3.4.1
44-zope.deferredimport==3.5.3
45-zope.deprecation==3.4.1
46-zope.dottedname==3.4.6
47-zope.dublincore==3.8.2
48-zope.error==3.7.4
49-zope.event==3.5.2
50-zope.exceptions==3.6.2
51-zope.filerepresentation==3.6.1
52-zope.formlib==4.0.6
53-zope.hookable==3.4.1
54-#zope.i18n==3.7.4
55-zope.i18n==4.3.1
56-zope.i18nmessageid==3.5.3
57-zope.index==3.6.4
58-#zope.interface==3.7.0
59-# Upgrade from ZTK 1.1.6 for ZCML registration performance.
60-zope.interface==4.4.3
61-zope.intid==3.7.2
62-zope.keyreference==3.6.4
63-zope.lifecycleevent==3.6.2
64-zope.location==3.9.1
65-zope.login==1.0.0
66-zope.mimetype==1.3.1
67-zope.minmax==1.1.2
68-#zope.pagetemplate==3.5.2
69-zope.pagetemplate==4.3.0
70-zope.password==3.6.1
71-zope.pluggableauth==1.2
72-zope.principalannotation==3.6.1
73-zope.principalregistry==3.7.1
74-zope.processlifetime==1.0
75-zope.proxy==3.6.1
76-zope.ptresource==3.9.0
77-zope.publisher==3.12.6
78-zope.ramcache==1.0
79-zope.schema==3.7.1
80-zope.security==3.8.3
81-zope.securitypolicy==3.7.0
82-zope.sendmail==3.7.5
83-zope.sequencesort==3.4.0
84-zope.server==3.8.6
85-#zope.session==3.9.5
86-# XXX: downgraded to avoid 3.9.2 cookie calculation changes
87-zope.session==3.9.1
88-zope.site==3.9.2
89-zope.size==3.4.1
90-zope.structuredtext==3.5.1
91-#zope.tal==3.5.2
92-zope.tal==4.3.0
93-zope.tales==3.5.3
94-#zope.testing==3.10.3
95+zope.component[hook,zcml]==4.5
96+zope.componentvocabulary==2.2.0
97+zope.configuration==4.3.1
98+zope.container==4.2.2
99+zope.contentprovider==4.2.1
100+zope.contenttype==4.4
101+zope.copy==4.2
102+zope.copypastemove==4.1.0
103+zope.datetime==4.2.0
104+zope.deferredimport==4.3
105+zope.deprecation==4.4.0
106+zope.dottedname==4.3
107+zope.dublincore==4.2.0
108+zope.error==4.5.0
109+zope.event==4.4
110+zope.exceptions==4.3
111+zope.filerepresentation==4.2.0
112+zope.formlib==4.6.0
113+zope.hookable==4.2.0
114+zope.i18n==4.6.2
115+zope.i18nmessageid==4.3.1
116+zope.index==4.4.0
117+zope.interface==4.6.0
118+zope.intid==4.3.0
119+zope.keyreference==4.2.0
120+zope.lifecycleevent==4.3
121+zope.location==4.2
122+zope.login==2.1.0
123+zope.mimetype==2.4.0
124+zope.minmax==2.2.0
125+zope.pagetemplate==4.4.1
126+zope.password==4.3.1
127+zope.pluggableauth==2.3.0
128+zope.principalannotation==4.3.0
129+zope.principalregistry==4.2.0
130+zope.processlifetime==2.3.0
131+zope.proxy==4.3.1
132+zope.ptresource==4.2.0
133+zope.publisher==5.0.1
134+zope.ramcache==2.3
135+zope.schema==4.9.3
136+zope.security==4.3.1
137+zope.securitypolicy==4.3.1
138+zope.sendmail==5.0
139+#zope.session==4.3.0
140+# lp:~launchpad-committers/zope.session:launchpad
141+zope.session==4.3.0+lp1
142+zope.site==4.2.2
143+zope.size==4.3
144+zope.structuredtext==4.3
145+zope.tal==4.4
146+zope.tales==5.0
147 zope.testing==4.7
148-#zope.testrunner==4.0.4
149+#zope.testrunner==5.0
150 # lp:~launchpad-committers/zope.testrunner:launchpad
151 zope.testrunner[subunit]==5.1+lp2
152-zope.traversing==3.14.0
153-zope.viewlet==3.7.2
154+zope.traversing==4.3.1
155+zope.viewlet==4.2.1
156
157-# Deprecating
158+# Direct dependencies
159+BTrees==4.5.1
160+persistent==4.4.3
161+python-gettext==4.0
162+pytz==2018.9
163+setuptools==41.0.0
164+six==1.12.0
165+transaction==2.4.0
166
167-# Dependencies
168-#distribute==0.6.36
169-distribute==0.7.3
170-#docutils==0.7
171-docutils==0.14
172-Jinja2==2.5.5
173-mechanize==0.2.5
174-Paste==1.7.5.1
175-PasteDeploy==1.3.4
176-PasteScript==1.7.5
177-py==1.4.8
178-#Pygments==1.4
179-Pygments==2.2.0
180-#python-gettext==1.0
181-python-gettext==3.0
182-#python-subunit==0.0.7
183-python-subunit==1.3.0
184-#pytz==2014.10
185-pytz==2017.2
186+# zope.password needs these
187+bcrypt==3.1.6
188+cffi==1.12.2
189+pycparser==2.19
190+
191+# Python2-only
192+zope.untrustedpython==4.0.0
193+# Required by zope.untrustedpython
194 RestrictedPython==3.6.0
195-#setuptools==0.6c11
196-setuptools==36.4.0
197-#Sphinx==1.0.8
198-Sphinx==1.6.5
199-#testtools==0.9.12
200+
201+# Testing dependencies
202+ZConfig==3.4.0
203+ZODB==5.5.1
204+argparse==1.4.0
205+colorama==0.4.1
206+extras==1.0.0
207+fixtures==3.0.0
208+linecache2==1.0.0
209+manuel==1.10.1
210+pbr==5.1.3
211+pyparsing==2.4.0
212+python-mimeparse==1.6.0
213+python-subunit==1.3.0
214 testtools==2.3.0
215-transaction==1.1.1
216-z3c.recipe.sphinxdoc==0.0.8
217-zc.buildout==1.7.1
218-zc.lockfile==1.0.2
219-#ZConfig==2.8.0
220-ZConfig==2.9.1dev-20110728
221-zc.recipe.egg==1.3.2
222-zc.recipe.testrunner==1.4.0
223-zc.resourcelibrary==1.3.4
224-zdaemon==2.0.7
225-ZODB3==3.10.5
226-zope.mkzeoinstance==3.9.5
227+traceback2==1.4.0
228+unittest2==1.1.0
229+zc.lockfile==1.4
230+zdaemon==4.3
231+zodbpickle==1.0.3
232
233-# toolchain
234-#argparse==1.1
235-argparse==1.2.1
236-coverage==3.5.2
237-lxml==2.2.8
238-mr.developer==1.25
239-nose==1.1.2
240-tl.eggdeps==0.4
241-z3c.checkversions==0.4.1
242-z3c.recipe.compattest==0.13.1
243-z3c.recipe.depgraph==0.5
244-z3c.recipe.scripts==1.0.1
245-zope.kgs==1.2.0
246
247-# zopeapp-versions.cfg from ZTK 1.1.6, with some upgrades
248-# -------------------------------------------------------
249+# Testing tools
250+coverage==4.5.3
251+nose==1.3.7
252
253-# ZopeApp
254-zc.sourcefactory==0.7.0
255-zope.app.applicationcontrol==3.5.10
256-zope.app.appsetup==3.15.0
257-zope.app.debug==3.4.1
258-zope.app.http==3.9.0
259-zope.app.publication==3.12.0
260-#zope.app.wsgi==3.10.0
261-zope.app.wsgi==3.15.0
262-#zope.testbrowser==3.10.4
263-zope.testbrowser[wsgi]==5.5.1
264+# Documentation dependencies
265+# We have to keep a version < 2 to still support Python 2
266+Sphinx==1.8.5
267+docutils==0.14
268+imagesize==1.1.0
269+alabaster==0.7.12
270+babel==2.6.0
271+Jinja2==2.10.1
272+MarkupSafe==1.1.1
273+Pygments==2.3.1
274+snowballstemmer==1.2.1
275+lxml==4.4.1
276+repoze.sphinx.autointerface==0.8
277+#requests==2.21.0
278+requests==2.22.0
279+certifi==2019.3.9
280+#urllib3==1.24.1
281+urllib3==1.25.3
282+idna==2.8
283+chardet==3.0.4
284+sphinxcontrib-programoutput==0.14
285+sphinxcontrib-websupport==1.1.0
286+sphinx-rtd-theme==0.4.3
287+packaging==19.0
288+typing==3.6.6
289+z3c.recipe.sphinxdoc==1.1.0
290
291-# Deprecated
292-roman==1.4.0
293-#wsgi-intercept==0.4
294-# Upgrade from ZTK 1.1.5 to intercept lazr.restfulclient.
295-wsgi-intercept==0.5.1
296-zope.app.authentication==3.9.0
297-zope.app.basicskin==3.5.1
298-zope.app.broken==3.6.0
299-zope.app.component==3.9.3
300-zope.app.container==3.9.2
301-zope.app.content==3.5.1
302-zope.app.dependable==3.5.1
303-zope.app.error==3.5.3
304-zope.app.exception==3.6.3
305-zope.app.folder==3.5.2
306-zope.app.form==4.0.2
307-zope.app.generations==3.7.1
308-zope.app.i18n==3.6.4
309-zope.app.locales==3.6.2
310-zope.app.localpermission==3.7.2
311-zope.app.pagetemplate==3.11.2
312-zope.app.principalannotation==3.7.0
313-zope.app.publisher==3.10.2
314-zope.app.renderer==3.5.1
315-zope.app.rotterdam==3.5.3
316-zope.app.schema==3.5.0
317-zope.app.security==3.7.5
318-#zope.app.testing==3.8.1
319-zope.app.testing==3.10.0
320-zope.app.zcmlfiles==3.7.1
321-zope.app.zopeappgenerations==3.6.1
322-zope.generations==3.7.1
323+# ZTK buildout dependencies
324+collective.recipe.cmd==0.11
325+mr.developer==2.0.0
326+z3c.checkversions==1.1
327+z3c.recipe.compattest==1.0
328+zc.buildout==2.13.1
329+zc.recipe.egg==2.0.7
330+zc.recipe.testrunner==2.0.0
331
332 # Launchpad
333 # ---------
334
335 # Alphabetical, case-insensitive, please! :-)
336
337-alabaster==0.7.10
338 # lp:~launchpad/ampoule/lp
339 # post1 Don't add a process back to the ready set if it received an error
340 # such as a timeout.
341@@ -208,7 +173,6 @@ Automat==0.6.0
342 Babel==2.5.1
343 backports.functools-lru-cache==1.5
344 backports.lzma==0.0.3
345-bcrypt==3.1.4
346 BeautifulSoup==3.2.1
347 beautifulsoup4[lxml]==4.7.1
348 billiard==3.5.0.5
349@@ -216,10 +180,7 @@ bson==0.3.3
350 # lp:~launchpad/bzr/lp
351 bzr==2.6.0.lp.4
352 celery==4.1.1
353-certifi==2019.3.9
354-cffi==1.11.2
355 Chameleon==2.11
356-chardet==3.0.4
357 constantly==15.1.0
358 cookies==2.2.1
359 cryptography==2.7
360@@ -235,10 +196,8 @@ dulwich==0.18.6
361 elementtree==1.2.6-20050316
362 enum34==1.1.6
363 epydoc==3.0.1
364-extras==1.0.0
365 feedparser==5.2.1
366 feedvalidator==0.0.0DEV-r1049
367-fixtures==3.0.0
368 FormEncode==1.2.4
369 futures==3.2.0
370 geoip2==2.9.0
371@@ -247,8 +206,6 @@ gunicorn==19.8.1
372 html5browser==0.0.9
373 httplib2==0.8
374 hyperlink==18.0.0
375-idna==2.6
376-imagesize==0.7.1
377 importlib==1.0.2
378 importlib-resources==0.5
379 incremental==17.5.0
380@@ -259,7 +216,7 @@ jsautobuild==0.2
381 keyring==0.6.2
382 kombu==4.4.0
383 launchpad-buildd==159
384-launchpadlib==1.10.7
385+launchpadlib==1.10.9
386 lazr.authentication==0.1.1
387 lazr.batchnavigator==1.3.0
388 lazr.config==2.2.2
389@@ -275,7 +232,6 @@ lazr.uri==1.0.3
390 libnacl==1.3.6
391 lpjsmin==0.5
392 m2r==0.1.13
393-manuel==1.7.2
394 Markdown==2.3.1
395 martian==0.11
396 maxminddb==1.5.1
397@@ -294,15 +250,16 @@ oops-wsgi==0.0.8
398 ordereddict==1.1
399 oslo.config==1.3.0
400 paramiko==2.4.1
401+Paste==1.7.5.1
402+PasteDeploy==1.3.4
403+PasteScript==1.7.5
404 pathlib2==2.3.2
405-pbr==0.11.1
406 pgbouncer==0.0.8
407 prettytable==0.7.2
408 psutil==5.4.2
409 psycopg2==2.7.4
410 pyasn1==0.4.2
411 pyasn1-modules==0.2.1
412-pycparser==2.18
413 # lp:~launchpad/pygpgme/pthread
414 # lp1 Link against libgpgme-pthread for thread-safety.
415 pygpgme==0.3+lp1
416@@ -316,7 +273,6 @@ python-dateutil==1.5
417 python-debian==0.1.32
418 python-keystoneclient==0.7.1
419 python-memcached==1.58
420-python-mimeparse==0.1.4
421 # XXX: deryck 2012-08-10
422 # See lp:~deryck/python-openid/python-openid-fix1034376 which
423 # reapplied a patch from wgrant to get codehosting going again.
424@@ -324,7 +280,6 @@ python-openid==2.2.5-fix1034376
425 python-swiftclient==2.0.3
426 PyYAML==3.10
427 rabbitfixture==0.4.2
428-requests==2.22.0
429 requests-file==1.4.3
430 requests-toolbelt==0.9.1
431 responses==0.9.0
432@@ -335,11 +290,8 @@ setuptools-git==1.2
433 setuptools-scm==1.15.7
434 simplejson==3.8.2
435 SimpleTAL==4.3
436-six==1.12.0
437-snowballstemmer==1.2.1
438 soupmatchers==0.4
439 soupsieve==1.9
440-sphinxcontrib-websupport==1.0.1
441 # lp:~launchpad-committers/storm/lp
442 storm==0.21.0.99+lp413
443 subprocess32==3.2.6
444@@ -352,9 +304,6 @@ Twisted[conch,tls]==19.2.1
445 txAMQP==0.6.2
446 txfixtures==0.4.2
447 txpkgupload==0.2
448-typing==3.6.2
449-unittest2==1.1.0
450-urllib3==1.25.3
451 van.testing==3.0.0
452 vine==1.1.4
453 virtualenv-tools3==2.0.0
454@@ -363,12 +312,22 @@ waitress==1.3.1
455 WebOb==1.8.5
456 WebTest==2.0.33
457 wheel==0.29.0
458+wsgi-intercept==0.5.1
459 WSGIProxy2==0.4.6
460 wsgiref==0.1.2
461 z3c.pt==2.2.3
462 z3c.ptcompat==0.5.7
463 zc.zservertracelog==1.3.2
464-# Not in ZTK 1.1.5
465-zope.app.server==3.6.0
466-# Not in ZTK 1.1.5 (extracted from zope.app.schema)
467+zope.app.applicationcontrol==4.0.0
468+zope.app.appsetup==4.1.0
469+zope.app.debug==3.4.1
470+zope.app.dependable==3.5.1
471+zope.app.http==4.0.1
472+zope.app.pagetemplate==3.11.2
473+zope.app.publication==4.3.1
474+zope.app.publisher==3.10.2
475+zope.app.server==4.0.0
476+zope.app.wsgi[testlayer]==4.1.0
477+zope.server==3.8.6
478+zope.testbrowser==5.5.1
479 zope.vocabularyregistry==1.0.0
480diff --git a/lib/lp/app/browser/launchpadform.py b/lib/lp/app/browser/launchpadform.py
481index e676414..ac6dd15 100644
482--- a/lib/lp/app/browser/launchpadform.py
483+++ b/lib/lp/app/browser/launchpadform.py
484@@ -227,6 +227,16 @@ class LaunchpadFormView(LaunchpadView):
485 return {}
486
487 @property
488+ def invariant_context(self):
489+ """The context against which to check form invariants.
490+
491+ If None, invariants will only be checked against values in the form
492+ itself. This is useful for forms that create new objects, since
493+ their context may not be adaptable to their schema.
494+ """
495+ return self.context
496+
497+ @property
498 def action_url(self):
499 """Set the default action URL for the form."""
500
501@@ -320,7 +330,8 @@ class LaunchpadFormView(LaunchpadView):
502 widgets = form.Widgets(widgets, len(self.prefix) + 1)
503 for error in form.getWidgetsData(widgets, self.prefix, data):
504 self.errors.append(error)
505- for error in form.checkInvariants(self.form_fields, data):
506+ for error in form.checkInvariants(
507+ self.form_fields, data, self.invariant_context):
508 self.addError(error)
509 return self.errors
510
511diff --git a/lib/lp/app/doc/tales.txt b/lib/lp/app/doc/tales.txt
512index 265ca25..cc7606e 100644
513--- a/lib/lp/app/doc/tales.txt
514+++ b/lib/lp/app/doc/tales.txt
515@@ -1379,7 +1379,7 @@ Queries about permissions that don't exist will raise an exception:
516 >>> test_tales('person/required:mushroom.Badger', person=mark)
517 Traceback (most recent call last):
518 ...
519- ValueError: ('Undefined permission id', 'mushroom.Badger')
520+ ValueError: ('Undefined permission ID', 'mushroom.Badger')
521
522
523 The somevalue/enumvalue:ENUMVALUE helper
524diff --git a/lib/lp/app/stories/basics/xx-lowercase-redirection.txt b/lib/lp/app/stories/basics/xx-lowercase-redirection.txt
525index bd29394..41c3e40 100644
526--- a/lib/lp/app/stories/basics/xx-lowercase-redirection.txt
527+++ b/lib/lp/app/stories/basics/xx-lowercase-redirection.txt
528@@ -34,4 +34,4 @@ When doing a POST to an invalid URL, we get an error:
529 ... """)
530 HTTP/1.1 500 Internal Server Error
531 ...
532- </ul>POSTToNonCanonicalURL...
533+ </ul><p>POSTToNonCanonicalURL...
534diff --git a/lib/lp/bugs/stories/webservice/xx-bug-target.txt b/lib/lp/bugs/stories/webservice/xx-bug-target.txt
535index f0e1076..b49afd2 100644
536--- a/lib/lp/bugs/stories/webservice/xx-bug-target.txt
537+++ b/lib/lp/bugs/stories/webservice/xx-bug-target.txt
538@@ -111,7 +111,7 @@ Official tags must conform to the same format as ordinary tags.
539 ... tag='an invalid tag !!!'))
540 HTTP/1.1 400 Bad Request
541 ...
542- tag: an invalid tag !!!
543+ tag: ...an invalid tag !!!...
544
545 We can also access official tags as a list.
546
547diff --git a/lib/lp/registry/browser/distributionmirror.py b/lib/lp/registry/browser/distributionmirror.py
548index f13cc5e..fd671a0 100644
549--- a/lib/lp/registry/browser/distributionmirror.py
550+++ b/lib/lp/registry/browser/distributionmirror.py
551@@ -211,6 +211,7 @@ class DistributionMirrorAddView(LaunchpadFormView):
552 "ftp_base_url", "rsync_base_url", "speed", "country", "content",
553 "official_candidate",
554 ]
555+ invariant_context = None
556
557 @property
558 def label(self):
559diff --git a/lib/lp/registry/browser/poll.py b/lib/lp/registry/browser/poll.py
560index c75a204..83d92b8 100644
561--- a/lib/lp/registry/browser/poll.py
562+++ b/lib/lp/registry/browser/poll.py
563@@ -396,6 +396,7 @@ class PollAddView(LaunchpadFormView):
564 schema = IPoll
565 field_names = ["name", "title", "proposition", "allowspoilt", "dateopens",
566 "datecloses"]
567+ invariant_context = None
568
569 page_title = 'New poll'
570
571diff --git a/lib/lp/registry/browser/team.py b/lib/lp/registry/browser/team.py
572index 5a79d28..ba79b6c 100644
573--- a/lib/lp/registry/browser/team.py
574+++ b/lib/lp/registry/browser/team.py
575@@ -999,6 +999,7 @@ class TeamAddView(TeamFormMixin, HasRenewalPolicyMixin, LaunchpadFormView):
576 """View for adding a new team."""
577
578 schema = ITeam
579+ invariant_context = None
580 page_title = 'Register a new team in Launchpad'
581 label = page_title
582
583diff --git a/lib/lp/scripts/helpers.py b/lib/lp/scripts/helpers.py
584index 38583a6..a534c6c 100644
585--- a/lib/lp/scripts/helpers.py
586+++ b/lib/lp/scripts/helpers.py
587@@ -78,7 +78,7 @@ class TransactionFreeOperation:
588
589 @staticmethod
590 def any_active_transactions():
591- return transaction.manager._txn
592+ return transaction.manager.manager._txn
593
594 @classmethod
595 def __enter__(cls):
596diff --git a/lib/lp/services/messaging/tests/test_rabbit.py b/lib/lp/services/messaging/tests/test_rabbit.py
597index ae5a89c..6cd9f99 100644
598--- a/lib/lp/services/messaging/tests/test_rabbit.py
599+++ b/lib/lp/services/messaging/tests/test_rabbit.py
600@@ -391,7 +391,7 @@ class TestRabbit(RabbitTestCase):
601
602 def get_synced_sessions(self):
603 try:
604- syncs_set = transaction.manager._synchs
605+ syncs_set = transaction.manager.manager._synchs
606 except KeyError:
607 return set()
608 else:
609diff --git a/lib/lp/services/verification/browser/logintoken.py b/lib/lp/services/verification/browser/logintoken.py
610index b17c6b8..c15321d 100644
611--- a/lib/lp/services/verification/browser/logintoken.py
612+++ b/lib/lp/services/verification/browser/logintoken.py
613@@ -175,6 +175,7 @@ class ClaimTeamView(
614 field_names = [
615 'teamowner', 'display_name', 'description', 'membership_policy',
616 'defaultmembershipperiod', 'renewal_policy', 'defaultrenewalperiod']
617+ invariant_context = None
618 label = 'Claim Launchpad team'
619 custom_widget_description = CustomWidgetFactory(
620 TextAreaWidget, height=10, width=30)
621diff --git a/lib/lp/services/webapp/doc/test_adapter.txt b/lib/lp/services/webapp/doc/test_adapter.txt
622index 2adc5fe..656e4b1 100644
623--- a/lib/lp/services/webapp/doc/test_adapter.txt
624+++ b/lib/lp/services/webapp/doc/test_adapter.txt
625@@ -367,7 +367,7 @@ transaction will be doomed:
626 >>> transaction.commit()
627 Traceback (most recent call last):
628 ...
629- DoomedTransaction
630+ DoomedTransaction: transaction doomed, cannot commit
631 <BLANKLINE>
632
633 Cleanup:
634diff --git a/lib/lp/services/webapp/doc/webapp-authorization.txt b/lib/lp/services/webapp/doc/webapp-authorization.txt
635index 0a116c8..7269cbd 100644
636--- a/lib/lp/services/webapp/doc/webapp-authorization.txt
637+++ b/lib/lp/services/webapp/doc/webapp-authorization.txt
638@@ -25,7 +25,7 @@ If the permission doesn't exist, it raises an error:
639 >>> check_permission('mushroom.Badger', sample_person)
640 Traceback (most recent call last):
641 ...
642- ValueError: ('Undefined permission id', 'mushroom.Badger')
643+ ValueError: ('Undefined permission ID', 'mushroom.Badger')
644 >>> logout()
645
646
647diff --git a/lib/lp/services/webapp/doc/webapp-publication.txt b/lib/lp/services/webapp/doc/webapp-publication.txt
648index 2c2c608..5028368 100644
649--- a/lib/lp/services/webapp/doc/webapp-publication.txt
650+++ b/lib/lp/services/webapp/doc/webapp-publication.txt
651@@ -872,8 +872,8 @@ The user attribute is an empty string, when no user is logged in.
652 >>> request._publication_start = 1.345
653 >>> request._publication_thread_start = None
654 >>> publication.afterCall(request, None)
655- >>> txn.user
656- ''
657+ >>> print txn.user
658+ <BLANKLINE>
659
660 But if there is a logged in user, the transaction user attribute will
661 contain its ID (as well as an empty '/' path, which is a Zope artefact
662diff --git a/lib/lp/services/webapp/publication.py b/lib/lp/services/webapp/publication.py
663index 716dd2e..1a1c1a4 100644
664--- a/lib/lp/services/webapp/publication.py
665+++ b/lib/lp/services/webapp/publication.py
666@@ -219,7 +219,12 @@ class LaunchpadBrowserPublication(
667 # It is possible that request.principal is None if the principal has
668 # not been set yet.
669 if request.principal is not None:
670- txn.setUser(request.principal.id)
671+ # Zope sets the transaction's user attribute to a
672+ # space-separated pair of path and user ID, where the path is a
673+ # record of traversed objects. This is mostly a ZODB thing that
674+ # we don't care about, so just use something minimal that fits
675+ # the syntax.
676+ txn.user = u"/ %s" % (request.principal.id,)
677
678 return txn
679
680diff --git a/lib/lp/services/webapp/session.py b/lib/lp/services/webapp/session.py
681index 2d7161d..2861dec 100644
682--- a/lib/lp/services/webapp/session.py
683+++ b/lib/lp/services/webapp/session.py
684@@ -51,6 +51,8 @@ class LaunchpadCookieClientIdManager(CookieClientIdManager):
685 # It should be larger than our session expiry time.
686 self.cookieLifetime = 1 * YEARS
687 self._secret = None
688+ # Forbid browsers from exposing it to JS.
689+ self.httpOnly = True
690
691 def getClientId(self, request):
692 sid = self.getRequestId(request)
693@@ -104,9 +106,6 @@ class LaunchpadCookieClientIdManager(CookieClientIdManager):
694 cookie = request.response.getCookie(self.namespace)
695 uri = URI(request.getURL())
696
697- # Forbid browsers from exposing it to JS.
698- cookie['HttpOnly'] = True
699-
700 # Set secure flag on cookie.
701 if uri.scheme != 'http':
702 cookie['secure'] = True
703diff --git a/lib/lp/translations/browser/language.py b/lib/lp/translations/browser/language.py
704index cced791..ac18a36 100644
705--- a/lib/lp/translations/browser/language.py
706+++ b/lib/lp/translations/browser/language.py
707@@ -163,6 +163,7 @@ class LanguageAddView(LaunchpadFormView):
708 schema = ILanguage
709 field_names = ['code', 'englishname', 'nativename', 'pluralforms',
710 'pluralexpression', 'visible', 'direction']
711+ invariant_context = None
712 language = None
713
714 page_title = "Register a language"
715diff --git a/setup.py b/setup.py
716index 6a72cb8..30391e6 100644
717--- a/setup.py
718+++ b/setup.py
719@@ -242,9 +242,14 @@ setup(
720 'zope.app.publication',
721 'zope.app.publisher',
722 'zope.app.server',
723- 'zope.app.wsgi',
724+ 'zope.app.wsgi[testlayer]',
725 'zope.authentication',
726+ 'zope.browser',
727+ 'zope.browsermenu',
728+ 'zope.browserpage',
729+ 'zope.browserresource',
730 'zope.component[zcml]',
731+ 'zope.configuration',
732 'zope.contenttype',
733 'zope.datetime',
734 'zope.error',
735@@ -270,7 +275,7 @@ setup(
736 'zope.session',
737 'zope.tal',
738 'zope.tales',
739- 'zope.testbrowser[wsgi]',
740+ 'zope.testbrowser',
741 'zope.testing',
742 'zope.testrunner[subunit]',
743 'zope.traversing',