Merge lp:~jml/launchpad/flush-top-level into lp:launchpad

Proposed by Jonathan Lange
Status: Merged
Approved by: Jonathan Lange
Approved revision: no longer in the source branch.
Merged at revision: 12472
Proposed branch: lp:~jml/launchpad/flush-top-level
Merge into: lp:launchpad
Diff against target: 1617 lines (+221/-894)
37 files modified
.bzrignore (+1/-0)
BRANCH.TODO (+0/-5)
Makefile (+13/-37)
README (+3/-3)
benchmarks/Auth.conf (+0/-101)
benchmarks/Frontpage.conf (+0/-103)
benchmarks/ShipIt.conf (+0/-102)
benchmarks/test_auth.py (+0/-83)
benchmarks/test_frontpage.py (+0/-31)
benchmarks/test_shipit.py (+0/-219)
bzrplugins/optional/README (+4/-0)
lib/canonical/config/__init__.py (+4/-2)
lib/canonical/config/tests/test_config_lookup.py (+1/-1)
lib/canonical/launchpad/doc/todo.txt (+0/-10)
lib/canonical/launchpad/scripts/__init__.py (+1/-1)
lib/canonical/launchpad/scripts/runlaunchpad.py (+6/-2)
lib/canonical/launchpad/testing/googletestservice.py (+4/-1)
lib/canonical/launchpad/webapp/publication.py (+3/-1)
lib/canonical/testing/layers.py (+9/-5)
lib/lp/app/templates/base-layout.pt (+0/-2)
lib/lp/app/versioninfo.py (+2/-18)
lib/lp/codehosting/__init__.py (+1/-1)
lib/lp/services/osutils.py (+37/-2)
lib/lp/services/tests/test_osutils.py (+50/-0)
run.gdb (+0/-1)
setup.py (+1/-1)
site.zcml (+11/-11)
test.config (+0/-116)
todo/debbugssync.txt (+0/-9)
todo/malone.txt (+0/-8)
utilities/snakefood/Makefile (+38/-0)
utilities/snakefood/README (+4/-0)
utilities/snakefood/lp-sfood-packages (+2/-0)
version.txt (+0/-1)
zcml/README (+24/-0)
zcml/ftesting.zcml (+2/-0)
zdaemon.conf (+0/-17)
To merge this branch: bzr merge lp:~jml/launchpad/flush-top-level
Reviewer Review Type Date Requested Status
Francis J. Lacoste (community) Approve
Review via email: mp+50374@code.launchpad.net

Commit message

[r=flacoste][no-qa] Clear up many of the top level files in the Launchpad tree.

Description of the change

This branch aims to clean up the top level directory of the Launchpad tree.

For a very long time now, it has been full of all sorts of things that no one really understands. The more clutter that's there, the harder it is for anyone trying to explore the project.

Move zcml files into 'zcml/':
  This is with the exception of 'site.zcml', which is referred to by external
  configuration files. I've had to change some code to look for zcml files in
  the right place.

Delete 'todo':
  Anything that's still todo from four years ago can safely be said to have been
  forgotten.

Delete BRANCH.TODO:
  This was a neat little mechanism, but there are other ways of achieving the same
  thing that don't put an extra cognitive load on people navigating the Launchpad
  code base.

Delete benchmarks:
  Francis says these were added for a sprint and are not needed any more.

Delete version.txt:
  We no longer put the version of Launchpad in the tree. I changed
  lp.app.versioninfo accordingly.

Delete test.config, zdaemon.conf:
  Simply unused.

Delete 'logs/':
  This directory *is* used when we run stuff in development environments, but it contains
  no versioned data. I've removed it from the tree and changed the Makefile to generate it
  when necessary.

Delete 'run.gdb':
  This was just a file that said 'run', because gdb doesn't let you specify commands
  for it in any other way. I've deleted the file and had the relevant make target create
  one.

Moved 'optionalbzrplugins' to 'bzrplugins/optional':
  This seems to be just as clear and less clutter in the top level.

Moved snakefood stuff:
  The "snakefood" stuff is Python package dependency analysis that I added ages ago.
  It's not important enough to clutter the root of the tree.

I've updated or added documentation where I could.

This change is potentially disruptive, both to developers and to production deployments. I'll start a full test suite run now.

To post a comment you must log in.
Revision history for this message
Francis J. Lacoste (flacoste) wrote :

Thanks a lot for this clean-up!

From a cursory glance, it looks good. A full test suite run and a deployment to qastaging will ensure that all the loose ends are tied up.

With the removal of benchmarks you can remove funkload and webunit from versions.cfg. Two less dependencies to build!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2011-02-04 17:21:05 +0000
3+++ .bzrignore 2011-02-25 18:10:41 +0000
4@@ -78,3 +78,4 @@
5 configs/testrunner-appserver_*
6 doc/_build
7 .idea
8+run.gdb
9
10=== removed file 'BRANCH.TODO'
11--- BRANCH.TODO 2011-02-10 15:43:21 +0000
12+++ BRANCH.TODO 1970-01-01 00:00:00 +0000
13@@ -1,5 +0,0 @@
14-# Put your TODOs for this branch here, then make sure it is empty before
15-# landing. There is a test to ensure it is empty in trunk. If there is
16-# stuff still here when you are ready to land, the items should probably
17-# be converted to bugs so they can be scheduled.
18-
19
20=== modified file 'Makefile'
21--- Makefile 2011-02-19 13:45:05 +0000
22+++ Makefile 2011-02-25 18:10:41 +0000
23@@ -125,6 +125,9 @@
24 lint-verbose: ${PY}
25 @bash ./bin/lint.sh -v
26
27+logs:
28+ mkdir logs
29+
30 xxxreport: $(PY)
31 ${PY} -t ./utilities/xxxreport.py -f csv -o xxx-report.csv ./
32
33@@ -134,7 +137,7 @@
34 pagetests: build
35 env PYTHONPATH=$(PYTHONPATH) bin/test test_pages
36
37-inplace: build
38+inplace: build logs clean_logs
39 mkdir -p $(CODEHOSTING_ROOT)/mirrors
40 mkdir -p $(CODEHOSTING_ROOT)/config
41 mkdir -p /var/tmp/bzrsync
42@@ -260,17 +263,17 @@
43 $(PY) cronscripts/merge-proposal-jobs.py -v
44
45 run: check_schema inplace stop
46- $(RM) logs/thread*.request
47 bin/run -r librarian,google-webservice,memcached -i $(LPCONFIG)
48
49-start-gdb: check_schema inplace stop support_files
50- $(RM) logs/thread*.request
51+run.gdb:
52+ echo 'run' > run.gdb
53+
54+start-gdb: check_schema inplace stop support_files run.gdb
55 nohup gdb -x run.gdb --args bin/run -i $(LPCONFIG) \
56 -r librarian,google-webservice
57 > ${LPCONFIG}-nohup.out 2>&1 &
58
59 run_all: check_schema inplace stop
60- $(RM) logs/thread*.request
61 bin/run -r librarian,sftp,forker,mailman,codebrowse,google-webservice,memcached \
62 -i $(LPCONFIG)
63
64@@ -284,7 +287,6 @@
65 $(PY) scripts/stop-loggerhead.py
66
67 run_codehosting: check_schema inplace stop
68- $(RM) logs/thread*.request
69 bin/run -r librarian,sftp,forker,codebrowse -i $(LPCONFIG)
70
71 start_librarian: compile
72@@ -360,7 +362,10 @@
73 $(RM) -r build
74 $(RM) _pythonpath.py
75
76-clean: clean_js clean_buildout
77+clean_logs:
78+ $(RM) logs/thread*.request
79+
80+clean: clean_js clean_buildout clean_logs
81 $(MAKE) -C sourcecode/pygettextpo clean
82 # XXX gary 2009-11-16 bug 483782
83 # The pygettextpo Makefile should have this next line in it for its make
84@@ -374,7 +379,6 @@
85 -name '*.lo' -o -name '*.py[co]' -o -name '*.dll' -o \
86 -name '*.pt.py' \) \
87 -print0 | xargs -r0 $(RM)
88- $(RM) logs/thread*.request
89 $(RM) -r lib/mailman
90 $(RM) -rf lib/canonical/launchpad/icing/build/*
91 $(RM) -rf $(CODEHOSTING_ROOT)
92@@ -398,7 +402,6 @@
93 # /var/tmp/launchpad_mailqueue is created read-only on ec2test
94 # instances.
95 if [ -w /var/tmp/launchpad_mailqueue ]; then $(RM) -rf /var/tmp/launchpad_mailqueue; fi
96- $(RM) -f lp.sfood lp-clustered.sfood lp-clustered.dot lp-clustered.svg
97
98
99 realclean: clean
100@@ -453,33 +456,6 @@
101 # idutils ID file
102 bin/tags -i
103
104-lp.sfood:
105- # Generate import dependency graph
106- sfood -i -u -I lib/sqlobject -I lib/schoolbell -I lib/devscripts \
107- -I lib/contrib -I lib/canonical/not-used lib/canonical \
108- lib/lp 2>/dev/null | grep -v contrib/ \
109- | grep -v sqlobject | grep -v BeautifulSoup | grep -v psycopg \
110- | grep -v schoolbell > lp.sfood.tmp
111- mv lp.sfood.tmp lp.sfood
112-
113-
114-lp-clustered.sfood: lp.sfood lp-sfood-packages
115- # Cluster the import dependency graph
116- sfood-cluster -f lp-sfood-packages < lp.sfood > lp-clustered.sfood.tmp
117- mv lp-clustered.sfood.tmp lp-clustered.sfood
118-
119-
120-lp-clustered.dot: lp-clustered.sfood
121- # Build the visual graph
122- sfood-graph -p < lp-clustered.sfood > lp-clustered.dot.tmp
123- mv lp-clustered.dot.tmp lp-clustered.dot
124-
125-
126-lp-clustered.svg: lp-clustered.dot
127- # Render to svg
128- dot -Tsvg < lp-clustered.dot > lp-clustered.svg.tmp
129- mv lp-clustered.svg.tmp lp-clustered.svg
130-
131 PYDOCTOR = pydoctor
132 PYDOCTOR_OPTIONS =
133
134@@ -495,4 +471,4 @@
135 check_merge_ui pull scan sync_branches reload-apache hosted_branches \
136 check_db_merge check_mailman check_config jsbuild jsbuild_lazr \
137 clean_js clean_buildout buildonce_eggs build_eggs sprite_css \
138- sprite_image css_combine compile check_schema pydoctor
139+ sprite_image css_combine compile check_schema pydoctor clean_logs \
140
141=== modified file 'README'
142--- README 2010-08-10 18:20:12 +0000
143+++ README 2011-02-25 18:10:41 +0000
144@@ -95,12 +95,12 @@
145 when buildout is run. If you want to change the behaviour of bin/test,
146 look here.
147
148- bzrplugins/, optionalbzrplugins/
149+ bzrplugins/
150 Bazaar plugins used in running Launchpad.
151
152 sourcecode/
153 A directory into which we symlink branches of some of Launchpad's
154 dependencies. Don't ask.
155
156-You never have to care about 'benchmarks', 'override-includes' or
157-'package-includes'.
158+ zcml/
159+ Various configuration files for the Zope services. Angels fear to tread.
160
161=== removed directory 'benchmarks'
162=== removed file 'benchmarks/Auth.conf'
163--- benchmarks/Auth.conf 2009-08-07 07:33:56 +0000
164+++ benchmarks/Auth.conf 1970-01-01 00:00:00 +0000
165@@ -1,101 +0,0 @@
166-# FunkLoad test configuration file
167-# $Id: $
168-
169-
170-# ------------------------------------------------------------
171-# Main section
172-#
173-[main]
174-title=Auth
175-description=Testing load with basic authentication to Launchpad
176-login=foo@mailinator.com
177-password=test
178-
179-# the server url to test.
180-url=https://staging.launchpad.net
181-
182-# ------------------------------------------------------------
183-# Tests description and configuration
184-#
185-[test_auth]
186-description=Does the login to Launchpad page.
187-
188-
189-# ------------------------------------------------------------
190-# Credential access
191-#
192-[credential]
193-host=localhost
194-port=8007
195-
196-
197-# ------------------------------------------------------------
198-# Monitoring configuration
199-#
200-[monitor]
201-#hosts=localhost
202-
203-# Each host in [monitor]hosts should have a section
204-# with a 'port' and 'description' keys
205-[localhost]
206-port=8008
207-description=The benching machine
208-
209-
210-# ------------------------------------------------------------
211-# Configuration for unit test mode fl-run-test
212-#
213-[ftest]
214-
215-# log_to destination =
216-# console - to the screen
217-# file - to a file
218-log_to = console file
219-
220-# log_path = path and file name to store log file
221-log_path = auth-test.log
222-
223-# result_path = path to store the xml result file
224-result_path = auth-test.xml
225-
226-# ok_codes = list of successfull HTTP response code default is 200:301:302
227-# ok_codes = 200:301:302
228-
229-# sleeptime_min = minimum amount of time in seconds to sleep between requests
230-# to the host
231-sleep_time_min = 0
232-
233-# sleeptime_max = maximum amount of time in seconds to sleep between requests
234-# to the host
235-sleep_time_max = 0
236-
237-
238-# ------------------------------------------------------------
239-# Configuration for bench mode fl-run-bench
240-#
241-[bench]
242-
243-# cycles = list of cycles with their number of concurrent users
244-cycles = 1:5:10:20:40:80:160:200
245-
246-# duration = duration of a cycle in seconds
247-duration = 60
248-
249-# startup_delay = time to wait between starting-up threads in seconds
250-startup_delay = 0.2
251-
252-# sleep_time = time to wait between test in seconds
253-sleep_time = 1
254-
255-# cycle_time = time to wait between cycle in seconds
256-# We have a significant delay in case we had to terminate the previous
257-# cycle by restarting the service.
258-cycle_time = 45
259-
260-# same keys than in [ftest] section
261-log_to = file
262-log_path = auth-bench.log
263-result_path = auth-bench.xml
264-#ok_codes = 200:301:302
265-sleep_time_min = 0
266-sleep_time_max = 2
267
268=== removed file 'benchmarks/Frontpage.conf'
269--- benchmarks/Frontpage.conf 2009-07-16 17:58:57 +0000
270+++ benchmarks/Frontpage.conf 1970-01-01 00:00:00 +0000
271@@ -1,103 +0,0 @@
272-# FunkLoad test configuration file
273-# $Id: $
274-
275-
276-# ------------------------------------------------------------
277-# Main section
278-#
279-[main]
280-title=Front Page
281-description=Launchpad Front Page
282-
283-# the server url to test
284-url=http://launchpad.net
285-
286-# the User-Agent header to send default is 'FunkLoad/1.xx' examples:
287-#user_agent = Opera/8.0 (Windows NT 5.1; U; en)
288-#user_agent = Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
289-#user_agent = Mozilla/5.0 (X11; U; Linux i686; en; rv:1.7.10) Gecko/20050912 Firefox/1.0.6
290-
291-
292-# ------------------------------------------------------------
293-# Tests description and configuration
294-#
295-[test_frontpage]
296-description=Load the Launchpad front page.
297-
298-
299-# ------------------------------------------------------------
300-# Credential access
301-#
302-[credential]
303-host=localhost
304-port=8007
305-
306-
307-# ------------------------------------------------------------
308-# Monitoring configuration
309-#
310-[monitor]
311-#hosts=localhost
312-
313-# Each host in [monitor]hosts should have a section
314-# with a 'port' and 'description' keys
315-[localhost]
316-port=8008
317-description=The benching machine
318-
319-
320-# ------------------------------------------------------------
321-# Configuration for unit test mode fl-run-test
322-#
323-[ftest]
324-
325-# log_to destination =
326-# console - to the screen
327-# file - to a file
328-log_to = console file
329-
330-# log_path = path and file name to store log file
331-log_path = frontpage-test.log
332-
333-# result_path = path to store the xml result file
334-result_path = frontpage-test.xml
335-
336-# ok_codes = list of successfull HTTP response code default is 200:301:302
337-# ok_codes = 200:301:302
338-
339-# sleeptime_min = minimum amount of time in seconds to sleep between requests
340-# to the host
341-sleep_time_min = 0
342-
343-# sleeptime_max = maximum amount of time in seconds to sleep between requests
344-# to the host
345-sleep_time_max = 0
346-
347-
348-# ------------------------------------------------------------
349-# Configuration for bench mode fl-run-bench
350-#
351-[bench]
352-
353-# cycles = list of cycles with their number of concurrent users
354-cycles = 1:2:3
355-
356-# duration = duration of a cycle in seconds
357-duration = 30
358-
359-# startup_delay = time to wait between starting-up threads in seconds
360-startup_delay = 0.2
361-
362-# sleep_time = time to wait between test in seconds
363-sleep_time = 1
364-
365-# cycle_time = time to wait between cycle in seconds
366-cycle_time = 1
367-
368-# same keys than in [ftest] section
369-log_to = file
370-log_path = frontpage-bench.log
371-result_path = frontpage-bench.xml
372-#ok_codes = 200:301:302
373-sleep_time_min = 0
374-sleep_time_max = 2
375
376=== removed file 'benchmarks/ShipIt.conf'
377--- benchmarks/ShipIt.conf 2009-07-17 12:50:54 +0000
378+++ benchmarks/ShipIt.conf 1970-01-01 00:00:00 +0000
379@@ -1,102 +0,0 @@
380-# FunkLoad test configuration file
381-# $Id: $
382-
383-
384-# ------------------------------------------------------------
385-# Main section
386-#
387-[main]
388-title=ShipIt
389-description=ShipIt load test
390-
391-# the server url to test.
392-url=https://shipit.staging.launchpad.net
393-
394-# Database connection string to the Launchpad database.
395-database_conninfo=dbname=lpmain_staging host=localhost port=55435
396-
397-# ------------------------------------------------------------
398-# Tests description and configuration
399-#
400-[test_shipit]
401-description=Create an account, request cds, cancel order.
402-
403-
404-# ------------------------------------------------------------
405-# Credential access
406-#
407-[credential]
408-host=localhost
409-port=8007
410-
411-
412-# ------------------------------------------------------------
413-# Monitoring configuration
414-#
415-[monitor]
416-#hosts=localhost
417-
418-# Each host in [monitor]hosts should have a section
419-# with a 'port' and 'description' keys
420-[localhost]
421-port=8008
422-description=The benching machine
423-
424-
425-# ------------------------------------------------------------
426-# Configuration for unit test mode fl-run-test
427-#
428-[ftest]
429-
430-# log_to destination =
431-# console - to the screen
432-# file - to a file
433-log_to = console file
434-
435-# log_path = path and file name to store log file
436-log_path = shipit-test.log
437-
438-# result_path = path to store the xml result file
439-result_path = shipit-test.xml
440-
441-# ok_codes = list of successfull HTTP response code default is 200:301:302
442-# ok_codes = 200:301:302
443-
444-# sleeptime_min = minimum amount of time in seconds to sleep between requests
445-# to the host
446-sleep_time_min = 0
447-
448-# sleeptime_max = maximum amount of time in seconds to sleep between requests
449-# to the host
450-sleep_time_max = 0
451-
452-
453-# ------------------------------------------------------------
454-# Configuration for bench mode fl-run-bench
455-#
456-[bench]
457-
458-# cycles = list of cycles with their number of concurrent users
459-cycles = 1:5:10:20:40:80:160:200
460-
461-# duration = duration of a cycle in seconds
462-duration = 60
463-
464-# startup_delay = time to wait between starting-up threads in seconds
465-startup_delay = 0.2
466-
467-# sleep_time = time to wait between test in seconds
468-sleep_time = 1
469-
470-# cycle_time = time to wait between cycle in seconds
471-# We have a significant delay in case we had to terminate the previous
472-# cycle by restarting the service.
473-cycle_time = 45
474-
475-# same keys than in [ftest] section
476-log_to = file
477-log_path = shipit-bench.log
478-result_path = shipit-bench.xml
479-#ok_codes = 200:301:302
480-sleep_time_min = 0
481-sleep_time_max = 2
482
483=== removed file 'benchmarks/test_auth.py'
484--- benchmarks/test_auth.py 2009-08-07 07:45:09 +0000
485+++ benchmarks/test_auth.py 1970-01-01 00:00:00 +0000
486@@ -1,83 +0,0 @@
487-# Copyright 2009 Canonical Ltd. This software is licensed under the
488-# GNU Affero General Public License version 3 (see the file LICENSE).
489-
490-"""Basic login to launchpad test."""
491-
492-__metaclass__ = type
493-__all__ = []
494-
495-import re
496-import threading
497-import unittest
498-
499-from funkload.FunkLoadTestCase import FunkLoadTestCase
500-
501-
502-class Auth(FunkLoadTestCase):
503-
504- def setUp(self):
505- """Setting up test."""
506- self.logd("setUp")
507- self.server_url = self.conf_get('main', 'url')
508-
509- _error_re = re.compile('(?s)class="error message">(.*?)</')
510-
511- def assertNoFormErrors(self, response):
512- """Checks if the page returned ok and the login was sucessful."""
513- self.assertEquals(response.code, 200)
514- match = self._error_re.search(response.body)
515- if match is not None:
516- self.fail('Form contained error: %s' % match.group(1))
517-
518- def assertIsNotLoggedIn(self, response):
519- # Not sure if this checking is needed.
520- self.assertEquals(response.code, 200)
521- match = response.body.find('If this is not you, please'
522- '<a href="/+logout">log out now</a>')
523- if match != -1:
524- self.fail('Test failed: this user is already logged in.')
525-
526- def test_auth(self):
527- """Runs the steps of a simple Launchpad login."""
528- self.logd("test_auth")
529-
530- server_url = self.server_url
531-
532- # Get the login page
533- response = self.get(server_url + "/+login", description="GET /+login")
534- self.assertNoFormErrors(response)
535- self.assertIsNotLoggedIn(response)
536-
537- # The credentials of foo user, the loginator
538- email = self.conf_get('main', 'login')
539- password = self.conf_get('main', 'password')
540-
541- # Get only the first form of the page, the login one,
542- # and fill it
543- fields = response.extractForm(path=[('form',0)], include_submit=True)
544- fields['loginpage_email'] = email
545- fields['loginpage_password'] = password
546-
547- # Submit the login form.
548- response = self.post(
549- self.absolute_url(response, '/+login'),
550- fields, "POST /+login")
551- self.assertNoFormErrors(response)
552- self.assertIsNotLoggedIn(response)
553- self.logd("logged in sucessfully")
554-
555- def absolute_url(self, response, path):
556- """Calculate an absolute URL using the response and the path."""
557- return '%s://%s:%s%s' % (
558- response.protocol, response.server, response.port, path)
559-
560- def tearDown(self):
561- """Finishes the test."""
562- self.logd("tearDown.\n")
563-
564-
565-if __name__ in ('main', '__main__'):
566- unittest.main()
567-
568-
569-
570
571=== removed file 'benchmarks/test_frontpage.py'
572--- benchmarks/test_frontpage.py 2009-07-18 21:21:06 +0000
573+++ benchmarks/test_frontpage.py 1970-01-01 00:00:00 +0000
574@@ -1,31 +0,0 @@
575-# Copyright 2009 Canonical Ltd. This software is licensed under the
576-# GNU Affero General Public License version 3 (see the file LICENSE).
577-
578-"""Launchpad frontpage FunkLoad test"""
579-
580-__metaclass__ = type
581-__all__ = []
582-
583-import unittest
584-
585-from funkload.FunkLoadTestCase import FunkLoadTestCase
586-
587-
588-class Frontpage(FunkLoadTestCase):
589- """Test anonymous access to the Launchpad front page."""
590-
591- def setUp(self):
592- """Setting up test."""
593- self.logd("setUp")
594- self.server_url = self.conf_get('main', 'url')
595-
596- def test_frontpage(self):
597- self.get(self.server_url, description="Get /")
598-
599- def tearDown(self):
600- """Setting up test."""
601- self.logd("tearDown.\n")
602-
603-
604-if __name__ in ('main', '__main__'):
605- unittest.main()
606
607=== removed file 'benchmarks/test_shipit.py'
608--- benchmarks/test_shipit.py 2009-07-18 21:21:06 +0000
609+++ benchmarks/test_shipit.py 1970-01-01 00:00:00 +0000
610@@ -1,219 +0,0 @@
611-# Copyright 2009 Canonical Ltd. This software is licensed under the
612-# GNU Affero General Public License version 3 (see the file LICENSE).
613-
614-"""Basic ShipIt usage test."""
615-
616-__metaclass__ = type
617-__all__ = []
618-
619-import re
620-import threading
621-import unittest
622-
623-from funkload.FunkLoadTestCase import FunkLoadTestCase
624-from funkload.Lipsum import Lipsum
625-import psycopg2
626-
627-
628-class ShipIt(FunkLoadTestCase):
629-
630- db_connection = None
631- db_connection_lock = threading.Lock()
632-
633- def setUp(self):
634- """Setting up test."""
635- self.logd("setUp")
636-
637- self.server_url = self.conf_get('main', 'url')
638- self.database_conninfo = self.conf_get('main', 'database_conninfo')
639-
640- self.lipsum = Lipsum()
641-
642- if ShipIt.db_connection is None:
643- # We use a class variable for the database connection so the
644- # same connection is shared between threads. This is important
645- # for when we are running with hundreds of threads.
646- ShipIt.db_connection_lock.acquire()
647- try:
648- if ShipIt.db_connection is None:
649- assert psycopg2.threadsafety >= 2, (
650- "psycopg2 cannot share connections between threads")
651- self.logi(
652- 'Opening database connection "%s".'
653- % self.database_conninfo)
654- ShipIt.db_connection = psycopg2.connect(
655- self.database_conninfo)
656- ShipIt.db_connection.set_isolation_level(0)
657- finally:
658- ShipIt.db_connection_lock.release()
659-
660- def cursor(self):
661- return ShipIt.db_connection.cursor()
662-
663- def get_email_validation_token(self, email):
664- cur = self.cursor()
665- cur.execute("""
666- SELECT token FROM AuthToken
667- WHERE date_consumed IS NULL AND token_type=12 AND email=%s
668- """, (email,))
669- row = cur.fetchone()
670- if row is None:
671- return None
672- return row[0]
673-
674- _error_re = re.compile('(?s)class="error">.*?class="message">(.*?)</')
675-
676- def assertNoFormErrors(self, response):
677- self.assertEquals(response.code, 200)
678- match = self._error_re.search(response.body)
679- if match is not None:
680- self.fail('Form contained error "%s"' % match.group(1))
681-
682- def test_shipit(self):
683- server_url = self.server_url
684-
685- self.get(server_url + "/", description="GET /")
686-
687- response = self.get(server_url + "/login", description="Get /login")
688- response = response.postForm(
689- 0, self.post, {'submit': 'Continue'},
690- 'Post /+openid - OpenID authentication request')
691- self.assertNoFormErrors(response)
692-
693- # User is not logged on
694- email = 'user_%s@lp%s.example.com' % (
695- self.lipsum.getUniqWord(), self.lipsum.getUniqWord())
696- # response.postForm fails here - looks like a bug. The action
697- # on the form is a relative URL and response.postForm tries
698- # to retrieve it from localhost.
699- params = response.extractForm(include_submit=True)
700- params['field.email'] = email
701- params['field.action'] = 'createaccount'
702- response = self.post(
703- self.absolute_url(response, '/+login-register'),
704- params, "Post /+login-register - Create account")
705- self.assertNoFormErrors(response)
706-
707- # Pull the email validation token from the database and
708- # validate it.
709- token = self.get_email_validation_token(email)
710- self.assert_(token is not None, "No login token created")
711- newaccount_url = self.absolute_url(
712- response, '/token/%s/+newaccount' % token)
713- response = self.get(
714- newaccount_url, description="Get /token/[...]/+newaccount")
715-
716- # Complete the registration process.
717- displayname = self.lipsum.getSubject(2)
718- password = self.lipsum.getWord()
719- params = response.extractForm(include_submit=True)
720-
721- params.update({
722- 'field.displayname': displayname,
723- 'field.hide_email_addresses': 'on',
724- 'field.password': password,
725- 'field.password_dupe': password,
726- 'field.actions.continue': 'Continue'})
727- # At the moment, creating your account doesn't log you in
728- # immidiately so you might end up at a 403 page - Bug #400610
729- response = self.post(
730- newaccount_url, params, ok_codes=[200, 302, 303, 403],
731- description="Post /token/[...]/+newaccount")
732- # Keep hitting the /login link until it works.
733- while response.code == 403:
734- login_url = self.absolute_url(response, '/login')
735- response = self.get(login_url, description="Get /login")
736- if response.get_base_url() == '/myrequest':
737- break
738- response = response.postForm(
739- 0, self.post, {}, "Post /+openid")
740- if response.get_base_url() == '/+openid':
741- params = response.extractForm()
742- params['field.actions.auth'] = 'Sign In'
743- response = self.post(
744- self.absolute_url(response, '/+decide'), params,
745- description = "Post /+decide",
746- ok_codes=[200, 302, 303, 403])
747-
748- # Registration succeeded - should be on the order details page now.
749- self.assertEquals(response.get_base_url(), '/myrequest')
750-
751- # Request some CDs.
752- params = response.extractForm(include_submit=True)
753- params.update({
754- 'field.recipientdisplayname': displayname[:20],
755- 'field.addressline1': self.lipsum.getSubject(3)[:30],
756- 'field.addressline2': self.lipsum.getSubject(3)[:30],
757- 'field.city': self.lipsum.getSubject(1)[:30],
758- 'field.province': self.lipsum.getSubject(2)[:30],
759- 'field.postcode': self.lipsum.getSubject(1)[:20],
760- 'field.country': '212',
761- 'field.country-empty-marker': '1',
762- 'field.phone': self.lipsum.getPhoneNumber()[:16],
763- 'field.actions.continue': 'Submit Request'})
764- response = self.post(
765- self.absolute_url(response, '/myrequest'),
766- params, "Post /myrequest - Request CDs")
767- self.assertNoFormErrors(response)
768-
769- if response.body.find('Cancel Request') == -1:
770- open('dud.html', 'w').write(response.body)
771-
772- # Confirm the request worked.
773- self.assert_(
774- response.body.find('Cancel Request') != -1,
775- "Cancel button not found.")
776-
777- # Logout.
778- response = self.post(
779- server_url + "/+logout", description="Post /+logout")
780- self.assert_(
781- response.body.find('You have been logged out') != -1,
782- "No logged out notification.")
783-
784- # Attempt to login again, bringing up the login form.
785- response = self.get(server_url, description="Get /")
786- response = self.get(
787- server_url + "/login", description="Get /login")
788- response = response.postForm(
789- 0, self.post, {'submit': 'Continue'},
790- 'Post /+openid - OpenID authentication request')
791- self.assertNoFormErrors(response)
792-
793- # Submit the login form.
794- params = response.extractForm(include_submit=True)
795- params['field.email'] = email
796- params['field.password'] = password
797- params['field.action'] = 'login'
798- response = self.post(
799- self.absolute_url(response, '/+login-register'),
800- params, "Post /+login-register - Login to existing account")
801- self.assertNoFormErrors(response)
802- self.assertEquals(response.url, '/myrequest')
803-
804- # Cancel the CD request.
805- params = response.extractForm([('form', 1)], include_submit=True)
806- response = self.post(
807- self.absolute_url(response, '/myrequest'),
808- params, description="Post /myrequest - Cancel CD order.")
809- self.assertNoFormErrors(response)
810- self.assert_(
811- response.body.find('Cancel Request') == -1,
812- "Cancel button found.")
813-
814- # Don't log out - leave the session dangling like most real users
815- # do.
816-
817- def absolute_url(self, response, path):
818- """Calculate an absolute URL using the response and the path."""
819- return '%s://%s:%s%s' % (
820- response.protocol, response.server, response.port, path)
821-
822- def tearDown(self):
823- """Setting up test."""
824- self.logd("tearDown.\n")
825-
826-
827-
828-if __name__ in ('main', '__main__'):
829- unittest.main()
830
831=== renamed directory 'optionalbzrplugins' => 'bzrplugins/optional'
832=== added file 'bzrplugins/optional/README'
833--- bzrplugins/optional/README 1970-01-01 00:00:00 +0000
834+++ bzrplugins/optional/README 2011-02-25 18:10:41 +0000
835@@ -0,0 +1,4 @@
836+These are for plugins that we do *not* want loaded all of the time.
837+
838+Specifically, the code import system loads these plugins, but we do not want
839+the branch puller or scanner loading them.
840
841=== modified symlink 'bzrplugins/optional/git'
842=== target changed u'../sourcecode/bzr-git' => u'../../sourcecode/bzr-git/'
843=== modified symlink 'bzrplugins/optional/hg'
844=== target changed u'../sourcecode/bzr-hg' => u'../../sourcecode/bzr-hg'
845=== modified symlink 'bzrplugins/optional/svn'
846=== target changed u'../sourcecode/bzr-svn' => u'../../sourcecode/bzr-svn'
847=== modified file 'lib/canonical/config/__init__.py'
848--- lib/canonical/config/__init__.py 2010-10-25 12:11:43 +0000
849+++ lib/canonical/config/__init__.py 2011-02-25 18:10:41 +0000
850@@ -26,6 +26,8 @@
851
852 from canonical.launchpad.readonly import is_read_only
853
854+from lp.services.osutils import open_for_writing
855+
856
857 __all__ = [
858 'DatabaseConfig',
859@@ -239,8 +241,8 @@
860
861 Call this method before letting any ZCML processing occur.
862 """
863- loader_file = os.path.join(self.root, '+config-overrides.zcml')
864- loader = open(loader_file, 'w')
865+ loader_file = os.path.join(self.root, 'zcml/+config-overrides.zcml')
866+ loader = open_for_writing(loader_file, 'w')
867
868 print >> loader, """
869 <configure xmlns="http://namespaces.zope.org/zope">
870
871=== modified file 'lib/canonical/config/tests/test_config_lookup.py'
872--- lib/canonical/config/tests/test_config_lookup.py 2010-01-07 06:00:00 +0000
873+++ lib/canonical/config/tests/test_config_lookup.py 2011-02-25 18:10:41 +0000
874@@ -139,7 +139,7 @@
875 # Set that root to the temporary directory.
876 cfg.root = self.temp_config_root_dir
877 cfg.generate_overrides()
878- override_file = os.path.join(cfg.root, '+config-overrides.zcml')
879+ override_file = os.path.join(cfg.root, 'zcml/+config-overrides.zcml')
880 self.failUnless(
881 os.path.isfile(override_file), "Overrides file wasn't created.")
882
883
884=== removed file 'lib/canonical/launchpad/doc/todo.txt'
885--- lib/canonical/launchpad/doc/todo.txt 2008-06-19 02:55:59 +0000
886+++ lib/canonical/launchpad/doc/todo.txt 1970-01-01 00:00:00 +0000
887@@ -1,10 +0,0 @@
888-
889-= Ensure there are no outstanding TODO's =
890-
891- >>> todos = open('BRANCH.TODO').read()
892- >>> print todos
893- # Put your TODOs for this branch here, then make sure it is empty before
894- # landing. There is a test to ensure it is empty in trunk. If there is
895- # stuff still here when you are ready to land, the items should probably
896- # be converted to bugs so they can be scheduled.
897-
898
899=== modified file 'lib/canonical/launchpad/scripts/__init__.py'
900--- lib/canonical/launchpad/scripts/__init__.py 2010-12-20 03:21:03 +0000
901+++ lib/canonical/launchpad/scripts/__init__.py 2011-02-25 18:10:41 +0000
902@@ -71,7 +71,7 @@
903 scriptzcmlfilename = 'script.zcml'
904
905 scriptzcmlfilename = os.path.abspath(
906- os.path.join(config.root, scriptzcmlfilename))
907+ os.path.join(config.root, 'zcml', scriptzcmlfilename))
908
909 from zope.configuration import xmlconfig
910
911
912=== modified file 'lib/canonical/launchpad/scripts/runlaunchpad.py'
913--- lib/canonical/launchpad/scripts/runlaunchpad.py 2010-11-08 00:37:51 +0000
914+++ lib/canonical/launchpad/scripts/runlaunchpad.py 2011-02-25 18:10:41 +0000
915@@ -17,13 +17,14 @@
916 from zope.app.server.main import main
917
918 from canonical.config import config
919-from lp.services.mailman import runmailman
920 from canonical.launchpad.daemons import tachandler
921 from canonical.launchpad.testing import googletestservice
922 from canonical.lazr.pidfile import (
923 make_pidfile,
924 pidfile_path,
925 )
926+from lp.services.mailman import runmailman
927+from lp.services.osutils import ensure_directory_exists
928
929
930 def make_abspath(path):
931@@ -39,7 +40,7 @@
932
933 def launch(self):
934 """Run the service in a thread or external process.
935-
936+
937 May block long enough to kick it off, but must return control to
938 the caller without waiting for it to shutdown.
939 """
940@@ -308,6 +309,9 @@
941 # Create the ZCML override file based on the instance.
942 config.generate_overrides()
943
944+ # Many things rely on a directory called 'logs' existing in the current
945+ # working directory.
946+ ensure_directory_exists('logs')
947 with nested(*services):
948 # Store our process id somewhere
949 make_pidfile('launchpad')
950
951=== modified file 'lib/canonical/launchpad/testing/googletestservice.py'
952--- lib/canonical/launchpad/testing/googletestservice.py 2010-08-20 20:31:18 +0000
953+++ lib/canonical/launchpad/testing/googletestservice.py 2011-02-25 18:10:41 +0000
954@@ -29,6 +29,8 @@
955 pidfile_path,
956 )
957
958+from lp.services.osutils import ensure_directory_exists
959+
960 # Set up basic logging.
961 log = logging.getLogger(__name__)
962
963@@ -107,7 +109,7 @@
964 try:
965 try:
966 sock.connect((host, port))
967- except socket.error, err:
968+ except socket.error:
969 return False
970 else:
971 return True
972@@ -255,6 +257,7 @@
973 # Redirect our service output to a log file.
974 # pylint: disable-msg=W0602
975 global log
976+ ensure_directory_exists(os.path.dirname(config.google_test_service.log))
977 filelog = logging.FileHandler(config.google_test_service.log)
978 log.addHandler(filelog)
979 log.setLevel(logging.DEBUG)
980
981=== modified file 'lib/canonical/launchpad/webapp/publication.py'
982--- lib/canonical/launchpad/webapp/publication.py 2010-12-17 20:58:27 +0000
983+++ lib/canonical/launchpad/webapp/publication.py 2011-02-25 18:10:41 +0000
984@@ -85,6 +85,7 @@
985 )
986 from lp.services import features
987 from lp.services.features.flags import NullFeatureController
988+from lp.services.osutils import open_for_writing
989
990
991 METHOD_WRAPPER_TYPE = type({}.__setitem__)
992@@ -245,7 +246,8 @@
993 notify(StartRequestEvent(request))
994 request._traversalticks_start = tickcount.tickcount()
995 threadid = thread.get_ident()
996- threadrequestfile = open('logs/thread-%s.request' % threadid, 'w')
997+ threadrequestfile = open_for_writing(
998+ 'logs/thread-%s.request' % threadid, 'w')
999 try:
1000 request_txt = unicode(request).encode('UTF-8')
1001 except Exception:
1002
1003=== modified file 'lib/canonical/testing/layers.py'
1004--- lib/canonical/testing/layers.py 2011-02-24 13:02:42 +0000
1005+++ lib/canonical/testing/layers.py 2011-02-25 18:10:41 +0000
1006@@ -140,6 +140,10 @@
1007 WAIT_INTERVAL = datetime.timedelta(seconds=180)
1008
1009
1010+def set_up_functional_test():
1011+ return FunctionalTestSetup('zcml/ftesting.zcml')
1012+
1013+
1014 class LayerError(Exception):
1015 pass
1016
1017@@ -1019,7 +1023,7 @@
1018 # zope.publisher.paste.Application.
1019 request_cls, publication_cls = chooseClasses(
1020 environ['REQUEST_METHOD'], environ)
1021- publication = publication_cls(FunctionalTestSetup().db)
1022+ publication = publication_cls(set_up_functional_test().db)
1023 request = request_cls(environ['wsgi.input'], environ)
1024 request.setPublication(publication)
1025 # The rest of this function is an amalgam of
1026@@ -1049,9 +1053,9 @@
1027 @profiled
1028 def setUp(cls):
1029 FunctionalLayer.isSetUp = True
1030- FunctionalTestSetup().setUp()
1031+ set_up_functional_test().setUp()
1032
1033- # Assert that FunctionalTestSetup did what it says it does
1034+ # Assert that set_up_functional_test did what it says it does
1035 if not is_ca_available():
1036 raise LayerInvariantError("Component architecture failed to load")
1037
1038@@ -1059,7 +1063,7 @@
1039 # If we don't, it may issue extra queries depending on test order.
1040 canonical.launchpad.webapp.session.idmanager.secret
1041 # If our request publication factories were defined using ZCML,
1042- # they'd be set up by FunctionalTestSetup().setUp(). Since
1043+ # they'd be set up by set_up_functional_test().setUp(). Since
1044 # they're defined by Python code, we need to call that code
1045 # here.
1046 register_launchpad_request_publication_factories()
1047@@ -1087,7 +1091,7 @@
1048 transaction.begin()
1049
1050 # Fake a root folder to keep Z3 ZODB dependencies happy.
1051- fs = FunctionalTestSetup()
1052+ fs = set_up_functional_test()
1053 if not fs.connection:
1054 fs.connection = fs.db.open()
1055 root = fs.connection.root()
1056
1057=== modified file 'lib/lp/app/templates/base-layout.pt'
1058--- lib/lp/app/templates/base-layout.pt 2011-02-07 07:08:25 +0000
1059+++ lib/lp/app/templates/base-layout.pt 2011-02-25 18:10:41 +0000
1060@@ -4,8 +4,6 @@
1061 define-macro="master"
1062 tal:define="
1063 revno modules/lp.app.versioninfo/revno | string:unknown;
1064- release modules/lp.app.versioninfo/release;
1065- version string:Launchpad ${release} (r${revno});
1066 devmode modules/canonical.config/config/devmode;
1067 rooturl modules/canonical.launchpad.webapp.vhosts/allvhosts/configs/mainsite/rooturl;
1068 is_demo modules/canonical.config/config/launchpad/is_demo;
1069
1070=== modified file 'lib/lp/app/versioninfo.py'
1071--- lib/lp/app/versioninfo.py 2010-12-14 09:45:07 +0000
1072+++ lib/lp/app/versioninfo.py 2011-02-25 18:10:41 +0000
1073@@ -20,12 +20,8 @@
1074 will have appropriate values from version_info.
1075
1076 If that file exists, and contains invalid Python, there will be an error when
1077-this module is loaded. This module is imported into
1078-canonical/launchpad/__init__.py so that such errors are caught at start-up.
1079-
1080-This module also reads version.txt at the top of the tree (i.e. a sibling of
1081-bzr-version-info.py), which contains the Launchpad release number. If that
1082-file does not exist, we make something up.
1083+this module is loaded. This module is imported into lp/app/__init__.py so
1084+that such errors are caught at start-up.
1085 """
1086
1087 __all__ = [
1088@@ -56,15 +52,3 @@
1089 revno = versioninfo.get('revno')
1090 date = versioninfo.get('date')
1091 branch_nick = versioninfo.get('branch_nick')
1092-
1093-
1094-try:
1095- version_file = open('version.txt')
1096-except IOError:
1097- release = 'x.y.z'
1098-else:
1099- try:
1100- version_data = version_file.read()
1101- release = version_data.strip()
1102- finally:
1103- version_file.close()
1104
1105=== modified file 'lib/lp/codehosting/__init__.py'
1106--- lib/lp/codehosting/__init__.py 2010-02-21 22:01:19 +0000
1107+++ lib/lp/codehosting/__init__.py 2011-02-25 18:10:41 +0000
1108@@ -74,7 +74,7 @@
1109 def load_optional_plugin(plugin_name):
1110 """Load the plugin named `plugin_name` from optionalbzrplugins/."""
1111 from bzrlib import plugins
1112- optional_plugin_dir = os.path.join(config.root, 'optionalbzrplugins')
1113+ optional_plugin_dir = os.path.join(config.root, 'bzrplugins/optional')
1114 if optional_plugin_dir not in plugins.__path__:
1115 plugins.__path__.append(optional_plugin_dir)
1116 __import__("bzrlib.plugins.%s" % plugin_name)
1117
1118=== modified file 'lib/lp/services/osutils.py'
1119--- lib/lp/services/osutils.py 2010-08-20 20:31:18 +0000
1120+++ lib/lp/services/osutils.py 2011-02-25 18:10:41 +0000
1121@@ -5,10 +5,12 @@
1122
1123 __metaclass__ = type
1124 __all__ = [
1125+ 'ensure_directory_exists',
1126+ 'kill_by_pidfile',
1127+ 'open_for_writing',
1128 'override_environ',
1129+ 'remove_if_exists',
1130 'remove_tree',
1131- 'kill_by_pidfile',
1132- 'remove_if_exists',
1133 'two_stage_kill',
1134 'until_no_eintr',
1135 ]
1136@@ -89,3 +91,36 @@
1137 raise
1138 else:
1139 raise
1140+
1141+
1142+def ensure_directory_exists(directory, mode=0777):
1143+ """Create 'directory' if it doesn't exist.
1144+
1145+ :return: True if the directory had to be created, False otherwise.
1146+ """
1147+ try:
1148+ os.makedirs(directory, mode=mode)
1149+ except OSError, e:
1150+ if e.errno == errno.EEXIST:
1151+ return False
1152+ raise
1153+ return True
1154+
1155+
1156+def open_for_writing(filename, mode, dirmode=0777):
1157+ """Open 'filename' for writing, creating directories if necessary.
1158+
1159+ :param filename: The path of the file to open.
1160+ :param mode: The mode to open the filename with. Should be 'w', 'a' or
1161+ something similar. See ``open`` for more details. If you pass in
1162+ a read-only mode (e.g. 'r'), then we'll just accept that and return
1163+ a read-only file-like object.
1164+ :param dirmode: The mode to use to create directories, if necessary.
1165+ :return: A file-like object that can be used to write to 'filename'.
1166+ """
1167+ try:
1168+ return open(filename, mode)
1169+ except IOError, e:
1170+ if e.errno == errno.ENOENT:
1171+ os.makedirs(os.path.dirname(filename), mode=dirmode)
1172+ return open(filename, mode)
1173
1174=== modified file 'lib/lp/services/tests/test_osutils.py'
1175--- lib/lp/services/tests/test_osutils.py 2010-08-19 11:29:36 +0000
1176+++ lib/lp/services/tests/test_osutils.py 2011-02-25 18:10:41 +0000
1177@@ -12,6 +12,8 @@
1178 import unittest
1179
1180 from lp.services.osutils import (
1181+ ensure_directory_exists,
1182+ open_for_writing,
1183 remove_tree,
1184 until_no_eintr,
1185 )
1186@@ -46,6 +48,54 @@
1187 self.assertRaises(OSError, remove_tree, filename)
1188
1189
1190+class TestEnsureDirectoryExists(TestCase):
1191+ """Tests for 'ensure_directory_exists'."""
1192+
1193+ def test_directory_exists(self):
1194+ directory = self.makeTemporaryDirectory()
1195+ self.assertFalse(ensure_directory_exists(directory))
1196+
1197+ def test_directory_doesnt_exist(self):
1198+ directory = os.path.join(self.makeTemporaryDirectory(), 'foo/bar/baz')
1199+ self.assertTrue(ensure_directory_exists(directory))
1200+ self.assertTrue(os.path.isdir(directory))
1201+
1202+
1203+class TestOpenForWriting(TestCase):
1204+ """Tests for 'open_for_writing'."""
1205+
1206+ def test_opens_for_writing(self):
1207+ # open_for_writing opens a file for, umm, writing.
1208+ directory = self.makeTemporaryDirectory()
1209+ filename = os.path.join(directory, 'foo')
1210+ fp = open_for_writing(filename, 'w')
1211+ fp.write("Hello world!\n")
1212+ fp.close()
1213+ self.assertEqual("Hello world!\n", open(filename).read())
1214+
1215+ def test_opens_for_writing_append(self):
1216+ # open_for_writing can also open to append.
1217+ directory = self.makeTemporaryDirectory()
1218+ filename = os.path.join(directory, 'foo')
1219+ fp = open_for_writing(filename, 'w')
1220+ fp.write("Hello world!\n")
1221+ fp.close()
1222+ fp = open_for_writing(filename, 'a')
1223+ fp.write("Next line\n")
1224+ fp.close()
1225+ self.assertEqual("Hello world!\nNext line\n", open(filename).read())
1226+
1227+ def test_even_if_directory_doesnt_exist(self):
1228+ # open_for_writing will open a file for writing even if the directory
1229+ # doesn't exist.
1230+ directory = self.makeTemporaryDirectory()
1231+ filename = os.path.join(directory, 'foo', 'bar', 'baz', 'filename')
1232+ fp = open_for_writing(filename, 'w')
1233+ fp.write("Hello world!\n")
1234+ fp.close()
1235+ self.assertEqual("Hello world!\n", open(filename).read())
1236+
1237+
1238 class TestUntilNoEINTR(TestCase):
1239 """Tests for until_no_eintr."""
1240
1241
1242=== removed directory 'logs'
1243=== removed file 'run.gdb'
1244--- run.gdb 2008-07-31 21:47:45 +0000
1245+++ run.gdb 1970-01-01 00:00:00 +0000
1246@@ -1,1 +0,0 @@
1247-run
1248
1249=== modified file 'setup.py'
1250--- setup.py 2011-02-16 19:38:48 +0000
1251+++ setup.py 2011-02-25 18:10:41 +0000
1252@@ -82,7 +82,7 @@
1253 'zope.app.apidoc',
1254 'zope.app.appsetup',
1255 'zope.app.component',
1256- 'zope.app.dav', # ./package-includes/dav-configure.zcml
1257+ 'zope.app.dav', # ./zcml/package-includes/dav-configure.zcml
1258 'zope.app.error',
1259 'zope.app.exception',
1260 'zope.app.file',
1261
1262=== modified file 'site.zcml'
1263--- site.zcml 2010-07-21 10:26:48 +0000
1264+++ site.zcml 2011-02-25 18:10:41 +0000
1265@@ -4,20 +4,20 @@
1266
1267 <configure xmlns="http://namespaces.zope.org/zope">
1268
1269- <include file="zopeapp.zcml" />
1270+ <include file="zcml/zopeapp.zcml" />
1271 <!--<include package="zope.app" />-->
1272
1273 <!-- Session machinery -->
1274- <include file="zopeappsession.zcml" />
1275+ <include file="zcml/zopeappsession.zcml" />
1276
1277 <!-- Browser Configurations -->
1278- <include file="zopeappbrowser.zcml" />
1279+ <include file="zcml/zopeappbrowser.zcml" />
1280 <!-- <include package="zope.app" file="browser.zcml" /> -->
1281
1282 <include package="canonical" />
1283
1284- <include files="package-includes/*-meta.zcml" />
1285- <includeOverrides file="override-meta.zcml" />
1286+ <include files="zcml/package-includes/*-meta.zcml" />
1287+ <includeOverrides file="zcml/override-meta.zcml" />
1288
1289 <!-- package-includes/*-configure.zcml contains package configuration
1290 shared between a normal launchpad instance and the test suite.
1291@@ -25,17 +25,17 @@
1292 package-includes/*-configure-testing.zcml contain configuration
1293 that needs to be different between normal and test modes.
1294 -->
1295- <include files="package-includes/*-configure.zcml" />
1296- <include files="package-includes/*-configure-normal.zcml" />
1297+ <include files="zcml/package-includes/*-configure.zcml" />
1298+ <include files="zcml/package-includes/*-configure-normal.zcml" />
1299
1300 <!-- Provide local overrides of standard configurations-->
1301- <includeOverrides file="override-configure.zcml" />
1302- <includeOverrides file="override-configure-normal.zcml" />
1303+ <includeOverrides file="zcml/override-configure.zcml" />
1304+ <includeOverrides file="zcml/override-configure-normal.zcml" />
1305
1306- <include file="securitypolicy.zcml" />
1307+ <include file="zcml/securitypolicy.zcml" />
1308
1309 <!-- include request summarizer here so it only affects webapp -->
1310- <include file="summarizerequests.zcml" />
1311+ <include file="zcml/summarizerequests.zcml" />
1312
1313 <include package="zc.zservertracelog" />
1314
1315
1316=== removed file 'test.config'
1317--- test.config 2005-10-31 18:29:12 +0000
1318+++ test.config 1970-01-01 00:00:00 +0000
1319@@ -1,116 +0,0 @@
1320-# test.config: options for Zope Test Runner.
1321-# Use this file to set Test Runner options that you would
1322-# otherwise set at the command line.
1323-
1324-# LEVEL=<int>
1325-# Run the tests at the given level. See -a, --all.
1326-# LEVEL = 1
1327-
1328-# BUILD=<boolean>
1329-# Build extensions before testing. See -b.
1330-# BUILD = False
1331-
1332-# BUILD=<boolean>
1333-# Build extensions before testing. See -b.
1334-# BUILD = False
1335-
1336-# BUILD_INPLACE=<boolean>
1337-# With BUILD==True, tests will be run from src directory.
1338-# See -B.
1339-# BUILD_INPLACE = False
1340-
1341-# PYCHECKER=<boolean>
1342-# Use pychecker. See -c.
1343-# PYCHECKER = False
1344-
1345-# DEBUG=<boolean>
1346-# Run a debug version of test harness.
1347-# See -d.
1348-# DEBUG = False
1349-
1350-# DEBUGGER=<boolean>
1351-# whether to post-mortem with pdb.
1352-# See -D.
1353-# DEBUGGER = False
1354-
1355-# RUN_UNIT=<boolean>
1356-# RUN_FUNCTIONAL=<boolean>
1357-# Whether to run functional tests and/or unit tests.
1358-# Default behaviour is RUN_UNIT and RUN_FUNCTIONAL.
1359-# RUN_UNIT = True
1360-# RUN_FUNCTIONAL = True
1361-
1362-# GC_THRESHOLD=<None>|<int>
1363-# Set the garbage collection threshold.
1364-# See -g.
1365-# GC_THRESHOLD = None
1366-
1367-# GC_FLAGS=<list-of-str>
1368-# list of garbage collection flags to set.
1369-# See -G.
1370-# GC_FLAGS = []
1371-
1372-# KEEP_STALE_BYTECODE=<boolean>
1373-# Do not delete all stale bytecode before running tests.
1374-# See -k.
1375-
1376-# LIBDIR=<dirpath>
1377-# Search for tests starting in the specified start directory.
1378-# See -l.
1379-# LIBDIR = '/path/to/dir/'
1380-LIBDIR='lib'
1381-
1382-# LOOP=<boolean>
1383-# Keep running the selected tests in a loop.
1384-# See -L.
1385-# LOOP = False
1386-
1387-# PROGRESS=<boolean>
1388-# Show running PROGRESS. It can be combined with -v or -vv.
1389-# See -p.
1390-# PROGRESS = False
1391-
1392-# REFCOUNT=<boolean>
1393-# Look for refcount problems.
1394-# See -r.
1395-# REFCOUNT = False
1396-
1397-# TRACE=<boolean>
1398-# Use the trace module from Python for code coverage.
1399-# See -T.
1400-# TRACE = False
1401-
1402-# TIMETESTS=<int>
1403-# Time the individual tests and print a list of the top <int>, sorted from
1404-# longest to shortest.
1405-# See -t (which sets TIMETESTS=50).
1406-# TIMETESTS = 0
1407-
1408-# TIMESFN=<filepath>
1409-# File to which to write timing information.
1410-# See -t.
1411-# TIMESFN = '/path/to/file'
1412-
1413-# VERBOSE=<int>
1414-# Verbosity level. Set VERBOSE=0 for quiet.
1415-# VERBOSE = 0
1416-
1417-# TEST_DIRS=<list>
1418-# List of paths, limiting where tests are searched for.
1419-# See --dir.
1420-# TEST_DIRS = ['/path/to/tests/']
1421-TEST_DIRS=["canonical"]
1422-
1423-# GUI=<boolean>|"minimal"
1424-# Whether to run unittest GUI. Use string value "minimal" for the minimal GUI.
1425-# GUI = False
1426-
1427-
1428-# MODULE_FILTER=<str>
1429-# Regular expression (in string format) for matching test module paths
1430-# MODULE_FILTER = None
1431-
1432-# TEST_FILTER=<str>
1433-# Regular expression (in string format) for matching test names
1434-# TEST_FILTER = None
1435-
1436
1437=== removed directory 'todo'
1438=== removed file 'todo/debbugssync.txt'
1439--- todo/debbugssync.txt 2005-10-31 18:29:12 +0000
1440+++ todo/debbugssync.txt 1970-01-01 00:00:00 +0000
1441@@ -1,9 +0,0 @@
1442-
1443-test:
1444-
1445- * that malone bugs are never linked debian packages more than once, no
1446- matter how many times the sync process happens.
1447- * that the "Mark all merged bugs as duplicates of the lowest-numbered bug"
1448- logic works correctly in all cases
1449- * that the watch last checked and last updated timestamps are updated
1450-
1451
1452=== removed file 'todo/malone.txt'
1453--- todo/malone.txt 2009-02-18 09:05:32 +0000
1454+++ todo/malone.txt 1970-01-01 00:00:00 +0000
1455@@ -1,8 +0,0 @@
1456-
1457- - a proper CVE - Distro report
1458- - CVE relevance indicator
1459- - watch relevance indicator
1460- - make BugWatchSet.fromText find sourceforge
1461- - make it tell the user what changed when it returns to the bug page
1462- after editing a bug task
1463-
1464
1465=== added directory 'utilities/snakefood'
1466=== added file 'utilities/snakefood/Makefile'
1467--- utilities/snakefood/Makefile 1970-01-01 00:00:00 +0000
1468+++ utilities/snakefood/Makefile 2011-02-25 18:10:41 +0000
1469@@ -0,0 +1,38 @@
1470+LIB_DIR=../../lib
1471+
1472+default: lp-clustered.svg
1473+
1474+# Generate import dependency graph
1475+lp.sfood:
1476+ sfood -i -u -I $(LIB_DIR)/sqlobject -I $(LIB_DIR)/schoolbell \
1477+ -I $(LIB_DIR)/devscripts -I $(LIB_DIR)/contrib \
1478+ -I $(LIB_DIR)/canonical/not-used $(LIB_DIR)/canonical \
1479+ $(LIB_DIR)/lp 2>/dev/null | grep -v contrib/ \
1480+ | grep -v sqlobject | grep -v BeautifulSoup | grep -v psycopg \
1481+ | grep -v schoolbell | grep -v '/tests/' | grep -v '/ftests/' \
1482+ | grep -v 'canonical/config' > lp.sfood.tmp
1483+ mv lp.sfood.tmp lp.sfood
1484+
1485+
1486+# Cluster the import dependency graph
1487+lp-clustered.sfood: lp.sfood lp-sfood-packages
1488+ sfood-cluster -f lp-sfood-packages < lp.sfood > lp-clustered.sfood.tmp
1489+ mv lp-clustered.sfood.tmp lp-clustered.sfood
1490+
1491+
1492+# Build the visual graph
1493+lp-clustered.dot: lp-clustered.sfood
1494+ sfood-graph -p < lp-clustered.sfood > lp-clustered.dot.tmp
1495+ mv lp-clustered.dot.tmp lp-clustered.dot
1496+
1497+
1498+# Render to svg
1499+lp-clustered.svg: lp-clustered.dot
1500+ dot -Tsvg < lp-clustered.dot > lp-clustered.svg.tmp
1501+ mv lp-clustered.svg.tmp lp-clustered.svg
1502+
1503+clean:
1504+ $(RM) -f lp.sfood lp-clustered.sfood lp-clustered.dot lp-clustered.svg
1505+
1506+
1507+.PHONY: clean
1508
1509=== added file 'utilities/snakefood/README'
1510--- utilities/snakefood/README 1970-01-01 00:00:00 +0000
1511+++ utilities/snakefood/README 2011-02-25 18:10:41 +0000
1512@@ -0,0 +1,4 @@
1513+Uses snakefood to generate dependency graphs of Launchpad, i.e. which packages
1514+use which other packages.
1515+
1516+To make the picture, run 'make', which will generate a nice SVG.
1517
1518=== renamed file 'lp-sfood-packages' => 'utilities/snakefood/lp-sfood-packages'
1519--- lp-sfood-packages 2011-02-25 10:12:09 +0000
1520+++ utilities/snakefood/lp-sfood-packages 2011-02-25 18:10:41 +0000
1521@@ -1,3 +1,4 @@
1522+lp/vostok
1523 lp/translations
1524 lp/testopenid
1525 lp/testing
1526@@ -21,6 +22,7 @@
1527 canonical/lp
1528 canonical/librarian
1529 canonical/lazr
1530+canonical/launchpad/webapp
1531 canonical/launchpad
1532 canonical/database/testing
1533 canonical/database
1534
1535=== removed file 'version.txt'
1536--- version.txt 2010-06-02 15:33:26 +0000
1537+++ version.txt 1970-01-01 00:00:00 +0000
1538@@ -1,1 +0,0 @@
1539-10.05
1540
1541=== added directory 'zcml'
1542=== added file 'zcml/README'
1543--- zcml/README 1970-01-01 00:00:00 +0000
1544+++ zcml/README 2011-02-25 18:10:41 +0000
1545@@ -0,0 +1,24 @@
1546+This is all a bit speculative.
1547+
1548+Entry points
1549+============
1550+
1551+These are the bits of ZCML that are explicitly loaded by Python code. These
1552+ZCML files in turn load other parts.
1553+
1554+ site.zcml
1555+ The big kahuna. Various config files (e.g. launchpad.conf) refer
1556+ to this file. For the time being, this must be available in the root
1557+ directory of the Launchpad tree, since production configuration files
1558+ depend on it being there.
1559+
1560+ ftesting.zcml
1561+ Used to configure the functional testing layer. Look in
1562+ canonical.testing.layers to see how it gets hooked in.
1563+
1564+ script.zcml
1565+ The main ZCML used for "scripts". Anything that runs in the Zopeless layer
1566+ uses this. See ``execute_zcml_for_scripts``.
1567+
1568+ script-testing.zcml
1569+ As for script.zcml, but for testing said scripts.
1570
1571=== renamed file 'ftesting.zcml' => 'zcml/ftesting.zcml'
1572--- ftesting.zcml 2009-07-13 18:15:02 +0000
1573+++ zcml/ftesting.zcml 2011-02-25 18:10:41 +0000
1574@@ -2,6 +2,8 @@
1575 GNU Affero General Public License version 3 (see the file LICENSE).
1576 -->
1577
1578+<!-- Used by the FunctionalLayer in canonical.testing.layers. -->
1579+
1580 <configure
1581 xmlns="http://namespaces.zope.org/zope"
1582 xmlns:rdb="http://namespaces.zope.org/rdb"
1583
1584=== renamed file 'override-configure-normal.zcml' => 'zcml/override-configure-normal.zcml'
1585=== renamed file 'override-configure-testing.zcml' => 'zcml/override-configure-testing.zcml'
1586=== renamed file 'override-configure.zcml' => 'zcml/override-configure.zcml'
1587=== renamed directory 'override-includes' => 'zcml/override-includes'
1588=== renamed file 'override-meta.zcml' => 'zcml/override-meta.zcml'
1589=== renamed directory 'package-includes' => 'zcml/package-includes'
1590=== renamed file 'script-testing.zcml' => 'zcml/script-testing.zcml'
1591=== renamed file 'script.zcml' => 'zcml/script.zcml'
1592=== renamed file 'securitypolicy.zcml' => 'zcml/securitypolicy.zcml'
1593=== renamed file 'summarizerequests.zcml' => 'zcml/summarizerequests.zcml'
1594=== renamed file 'zopeapp.zcml' => 'zcml/zopeapp.zcml'
1595=== renamed file 'zopeappbrowser.zcml' => 'zcml/zopeappbrowser.zcml'
1596=== renamed file 'zopeappsession.zcml' => 'zcml/zopeappsession.zcml'
1597=== removed file 'zdaemon.conf'
1598--- zdaemon.conf 2005-10-31 18:29:12 +0000
1599+++ zdaemon.conf 1970-01-01 00:00:00 +0000
1600@@ -1,17 +0,0 @@
1601-<runner>
1602- program bin/runzope
1603-</runner>
1604-
1605-<eventlog>
1606- # This sets up logging to both a file (z3.log) and to standard
1607- # output (STDOUT). The "path" setting can be a relative or absolute
1608- # filesystem path or the tokens STDOUT or STDERR.
1609-
1610- <logfile>
1611- path z3.log
1612- </logfile>
1613-
1614- <logfile>
1615- path STDOUT
1616- </logfile>
1617-</eventlog>