Merge lp:~gary/launchpad/zbuildout into lp:launchpad/db-devel
- zbuildout
- Merge into db-devel
Status: | Merged | ||||||||
---|---|---|---|---|---|---|---|---|---|
Approved by: | Francis J. Lacoste | ||||||||
Approved revision: | no longer in the source branch. | ||||||||
Merged at revision: | not available | ||||||||
Proposed branch: | lp:~gary/launchpad/zbuildout | ||||||||
Merge into: | lp:launchpad/db-devel | ||||||||
Diff against target: | None lines | ||||||||
To merge this branch: | bzr merge lp:~gary/launchpad/zbuildout | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Francis J. Lacoste (community) | Approve | ||
Review via email: mp+10181@code.launchpad.net |
Commit message
Description of the change
Gary Poster (gary) wrote : | # |
Francis J. Lacoste (flacoste) wrote : | # |
On August 14, 2009, Gary Poster wrote:
> Gary Poster has proposed merging lp:~gary/launchpad/zbuildout into
> lp:launchpad.
>
> Requested reviews:
> Francis J. Lacoste (flacoste)
>
> This branch changes us to use source distributions for our zope-related
> dependencies.
>
> Because we still are using some packages in sourcecode that want to be
> egg-based distributions-
> warning in _pythonpath and other scripts. This prevents some test failures
> that do not want to see any output from running a command.
>
> There are many other changes, of course.
>
> - Many are driven by changes in reprs of various objects--validation errors
> (LaunchpadValid
> (httperror_
>
> - Others are for API changes, like in zope.testing
> (lib/canonical/
>
> - I commented out the retry tests, as we have discussed.
>
> - Some tests expected zope files to be in the tree, so I had to switch to
> the pkg_resources API, or simply use more proper zcml in some cases.
>
> - There's a case or two of tokens needing to be converted from unicode to
> binary strings before they go into the URL, as with the
> lp:~gary/canonical-identity-provider/zbuildout branch that accompanies
> this one.
>
> - zope.schema set fields no longer support sets.Set, only the built-in set,
> which also resulted in some changes.
>
> - The transaction.begin API now does not expect to encounter an in-progress
> transaction (lib/canonical/
> lib/canonical/
>
> - I found a couple of tests that failed in isolation. Related changes are
> in lib/canonical/
> lib/canonical/
>
> - I'm not entirely sure how
>
> lib/lp/
>.txt ever passed before. The doctest syntax there was wrong.
>
> - I switched back to the feedvalidator solution that we had discussed way
> back when, rather than using the hacked version. I left a comment to
> describe the situation.
>
> - Some tests did a browser reload. That now has a different behavior,
> resubmitting forms and so on, so I reload the same URL instead.
>
> - I did a fly-by on
> lib/lp/
> a [testfix] problem I diagnosed yesterday, and using queryMultiAdapter hid
> the problem.
>
> versions.cfg comments out version numbers only when my changes represent a
> *previous* version that what was specified before. Happy to remove those
> as well.
>
> For this branch, I made changes and releases in the following packages:
>
> - zope.testing (modified trunk, released and used as zope.testing 3.8.1)
> - zope.security (modified trunk, released and used as zope.security 3.7.1)
> - zope.app.
> modified 3.4.3, released and used as zope.app.
>
> Diffs to the dependencies are below. For zope.testing and zope.security, I
> only show the commit that ...
Francis J. Lacoste (flacoste) wrote : | # |
Hi Gary,
OK, I managed to go through the changes. I have a bunch of trival comment,
nothing that should prevent you from merging this.
Finally! Good work!
status approved
review approve
> === modified file 'buildout-
> --- buildout-
> +++ buildout-
> @@ -11,3 +11,10 @@
> sys.path[0:0] = [${string-paths}]
> # Enable Storm's C extensions
> os.environ[
> +
> +# we don't want to bother tests or logs with these.
Capitalization.
> +import warnings
> +warnings.
> + 'ignore',
> + 'Module .+ was already imported from .+, but .+ is being added.*',
> + UserWarning)
> \ No newline at end of file
Missing newline.
> === modified file 'buildout.cfg'
> --- buildout.cfg 2009-08-05 03:30:57 +0000
> +++ buildout.cfg 2009-08-18 21:42:18 +0000
> @@ -56,6 +56,12 @@
> initialization = import os
> os.environ[
> os.environ.
'${configuratio
> + # this can hopefully be removed when Twisted is used as an
egg.
This should be an XXX pointing to a bug about using twisted as an egg. (And
please fix the capitalization of the comment.)
> === modified file 'lib/canonical/
> @@ -194,8 +195,10 @@
>
> def _setZConfig(self):
> """Modify the config, adding automatically generated settings"""
> - schemafile = os.path.join(
> - self.root, 'lib/zope/
> + self.root = TREE_ROOT
Why did you need to add that line back? I mean self.root should already be
defined properly.
> === modified file 'lib/canonical/
Instead of commenting everything here, why didn't you simply comment out the
line adding the MockDBTestCase to the suite in suite() ? I think this would
basically have the same effect. (With a comment explaining why this is
disabled.
> === modified file 'lib/canonical/
Same kind of comments here.
> === modified file 'setup.py'
> --- setup.py 2009-07-24 11:14:47 +0000
> +++ setup.py 2009-08-18 21:42:18 +0000
> @@ -20,26 +20,78 @@
> maintainer=
> description=('A unique collaboration and Bazaar code hosting platform '
> 'for software projects.'),
> - license='LGPL v3',
> + license='Affero GPL v3',
> + # this list should only contain direct dependencies-
> + # used in zcml.
> install_requires=[
> 'bzr',
> + 'chameleon.core',
> + 'chameleon.zpt',
> 'feedvalidator',
> 'funkload',
> 'launchpadlib',
> 'lazr.smtptest',
> 'lazr.uri',
> + 'mechanize',
Do we require mechanize? Isn't this an indirect dependency of
zope.testbrowser?
> > 'mocker',
> > 'oauth',
> > 'python-openid',
> 'pytz',
> + # This appears to be a broken indirect dependency from
zope.security:
> + 'RestrictedPython',
> 'setuptools',
> 'sour...
Gary Poster (gary) wrote : | # |
On Aug 18, 2009, at 4:57 PM, Francis J. Lacoste wrote:
> On August 14, 2009, Gary Poster wrote:
>> Gary Poster has proposed merging lp:~gary/launchpad/zbuildout into
>> lp:launchpad.
>>
>> Requested reviews:
>> Francis J. Lacoste (flacoste)
>>
>> This branch changes us to use source distributions for our zope-
>> related
>> dependencies.
>>
>> Because we still are using some packages in sourcecode that want to
>> be
>> egg-based distributions-
>> pkg_resources
>> warning in _pythonpath and other scripts. This prevents some test
>> failures
>> that do not want to see any output from running a command.
>>
>> There are many other changes, of course.
>>
>> - Many are driven by changes in reprs of various objects--
>> validation errors
>> (LaunchpadValid
>> (httperror_
>>
>> - Others are for API changes, like in zope.testing
>> (lib/canonical/
>>
>> - I commented out the retry tests, as we have discussed.
>>
>> - Some tests expected zope files to be in the tree, so I had to
>> switch to
>> the pkg_resources API, or simply use more proper zcml in some cases.
>>
>> - There's a case or two of tokens needing to be converted from
>> unicode to
>> binary strings before they go into the URL, as with the
>> lp:~gary/canonical-identity-provider/zbuildout branch that
>> accompanies
>> this one.
>>
>> - zope.schema set fields no longer support sets.Set, only the built-
>> in set,
>> which also resulted in some changes.
>>
>> - The transaction.begin API now does not expect to encounter an in-
>> progress
>> transaction (lib/canonical/
>> lib/canonical/
>>
>> - I found a couple of tests that failed in isolation. Related
>> changes are
>> in lib/canonical/
>> lib/canonical/
>>
>> - I'm not entirely sure how
>>
>> lib/lp/
>> tags-escape
>> .txt ever passed before. The doctest syntax there was wrong.
>>
>> - I switched back to the feedvalidator solution that we had
>> discussed way
>> back when, rather than using the hacked version. I left a comment to
>> describe the situation.
>>
>> - Some tests did a browser reload. That now has a different
>> behavior,
>> resubmitting forms and so on, so I reload the same URL instead.
>>
>> - I did a fly-by on
>> lib/lp/
>> that was
>> a [testfix] problem I diagnosed yesterday, and using
>> queryMultiAdapter hid
>> the problem.
>>
>> versions.cfg comments out version numbers only when my changes
>> represent a
>> *previous* version that what was specified before. Happy to remove
>> those
>> as well.
>>
>> For this branch, I made changes and releases in the following
>> packages:
>>
>> - zope.testing (modified trunk, released and used as zope.testing
>> 3.8.1)
>> - zope.security (modified trunk, released and used as zope.security
>> 3.7.1)
>> - zope.app.
Francis J. Lacoste (flacoste) wrote : | # |
On August 21, 2009, Gary Poster wrote:
> > Why not use sys.stdout.flush() here instead of using a newline?
>
> Because this feeds into the same new code in the parent process that
> now has the readline behavior. I don't think a flush is going to help
> if the listener is doing a readline. Maybe I could change the
> listener behavior for this case so that it no longer does a readline,
> and then I could do a flush here, but just sending a newline seemed
> like a nice one-line fix with no downside that I saw.
That's fine.
--
Francis J. Lacoste
<email address hidden>
Gary Poster (gary) wrote : | # |
On Aug 18, 2009, at 5:57 PM, Francis J. Lacoste wrote:
> Review: Approve
> Hi Gary,
>
> OK, I managed to go through the changes. I have a bunch of trival
> comment,
> nothing that should prevent you from merging this.
>
> Finally! Good work!
Thanks!
Responses below. I deleted the sections that I simply changed as you
suggested.
...
>> === modified file 'lib/canonical/
>> @@ -194,8 +195,10 @@
>>
>> def _setZConfig(self):
>> """Modify the config, adding automatically generated
>> settings"""
>> - schemafile = os.path.join(
>> - self.root, 'lib/zope/
>> + self.root = TREE_ROOT
>
> Why did you need to add that line back? I mean self.root should
> already be
> defined properly.
I *think* this must be a conflict resolution mistake of mine. I
removed the line again, and ec2test will tell me whether it is OK.
>
>> === modified file 'lib/canonical/
>
> Instead of commenting everything here, why didn't you simply comment
> out the
> line adding the MockDBTestCase to the suite in suite() ? I think
> this would
> basically have the same effect. (With a comment explaining why this is
> disabled.
The reason why was that there were many tests that were still able to
run. All of the ones that do not rely on the retry stuff still are
registered. Is that not worthwhile for some reason?
>> === modified file 'lib/canonical/
>
> Same kind of comments here.
Likewise. :-)
>> === modified file 'setup.py'
>> --- setup.py 2009-07-24 11:14:47 +0000
>> +++ setup.py 2009-08-18 21:42:18 +0000
>> @@ -20,26 +20,78 @@
>> maintainer=
>> description=('A unique collaboration and Bazaar code hosting
>> platform '
>> 'for software projects.'),
>> - license='LGPL v3',
>> + license='Affero GPL v3',
>> + # this list should only contain direct dependencies-
>> imported or
>> + # used in zcml.
>> install_requires=[
>> 'bzr',
>> + 'chameleon.core',
>> + 'chameleon.zpt',
>> 'feedvalidator',
>> 'funkload',
>> 'launchpadlib',
>> 'lazr.smtptest',
>> 'lazr.uri',
>> + 'mechanize',
>
> Do we require mechanize? Isn't this an indirect dependency of
> zope.testbrowser?
We have it here because of testbrowser, but we import it directly.
Here and in the other usage lists below I show you the uses I found
quickly today, reviewing your questions. There may be more.
lib/lp/
LinkNotFoundError
./lib/canonical
redirection.
./lib/lp/
31: >>> from mechanize import LinkNotFoundError
./lib/lp/
import LinkNotFoundError
>
>>> 'mocker',
>>> 'oauth',
>>> 'python-openid',
>> 'pytz',
>> + # This appears to be a broken indirect dependency from
> zope.security:
>> + ...
Francis J. Lacoste (flacoste) wrote : | # |
On August 21, 2009, Gary Poster wrote:
> On Aug 18, 2009, at 5:57 PM, Francis J. Lacoste wrote:
>
> >> === modified file 'lib/canonical/
> >
> > Instead of commenting everything here, why didn't you simply comment
> > out the
> > line adding the MockDBTestCase to the suite in suite() ? I think
> > this would
> > basically have the same effect. (With a comment explaining why this is
> > disabled.
>
> The reason why was that there were many tests that were still able to
> run. All of the ones that do not rely on the retry stuff still are
> registered. Is that not worthwhile for some reason?
It is. So that's fine.
>
> >> === modified file 'setup.py'
> >> --- setup.py 2009-07-24 11:14:47 +0000
> >> +++ setup.py 2009-08-18 21:42:18 +0000
> >> @@ -20,26 +20,78 @@
> >> maintainer=
> >> description=('A unique collaboration and Bazaar code hosting
> >> platform '
> >> 'for software projects.'),
> >> - license='LGPL v3',
> >> + license='Affero GPL v3',
> >> + # this list should only contain direct dependencies-
> >> imported or
> >> + # used in zcml.
> >> install_requires=[
> >> 'bzr',
> >> + 'chameleon.core',
> >> + 'chameleon.zpt',
> >> 'feedvalidator',
> >> 'funkload',
> >> 'launchpadlib',
> >> 'lazr.smtptest',
> >> 'lazr.uri',
> >> + 'mechanize',
> >
> > Do we require mechanize? Isn't this an indirect dependency of
> > zope.testbrowser?
>
> We have it here because of testbrowser, but we import it directly.
>
> Here and in the other usage lists below I show you the uses I found
> quickly today, reviewing your questions. There may be more.
>
> lib/lp/
> LinkNotFoundError
> ./lib/canonical
> redirection.
> ./lib/lp/
> 31: >>> from mechanize import LinkNotFoundError
> ./lib/lp/
> import LinkNotFoundError
>
> >>> 'mocker',
> >>> 'oauth',
> >>> 'python-openid',
> >>
> >> 'pytz',
> >> + # This appears to be a broken indirect dependency from
> >
> > zope.security:
> >> + 'RestrictedPython',
> >> 'setuptools',
> >> 'sourcecodegen',
> >> 'storm',
> >> - 'chameleon.core',
> >> - 'chameleon.zpt',
> >> + 'transaction',
> >> + 'wadllib',
> >> 'z3c.pt',
> >> 'z3c.ptcompat',
> >> - 'wadllib',
> >> + 'zc.zservertrac
> >> + 'zope.app.
> >> + 'zope.app.
> >> + 'zope.app.dav', # ./package-
> >
> > Really!?!
>
> Yeah, see that dav-configure.zcml thing. That's why the comment is
> there. Do you want me to try removing that file and then removing the
> dependency?
>
> Unless you are sure we can get rid of that zcml file, I think I'd
> prefer to make a bug for this, asking to investigate, and just leave
> things as...
Preview Diff
1 | === modified file 'buildout-templates/_pythonpath.py.in' |
2 | --- buildout-templates/_pythonpath.py.in 2009-06-24 20:22:29 +0000 |
3 | +++ buildout-templates/_pythonpath.py.in 2009-08-07 13:16:30 +0000 |
4 | @@ -11,3 +11,10 @@ |
5 | sys.path[0:0] = [${string-paths}] |
6 | # Enable Storm's C extensions |
7 | os.environ['STORM_CEXTENSIONS'] = '1' |
8 | + |
9 | +# we don't want to bother tests or logs with these. |
10 | +import warnings |
11 | +warnings.filterwarnings( |
12 | + 'ignore', |
13 | + 'Module .+ was already imported from .+, but .+ is being added.*', |
14 | + UserWarning) |
15 | \ No newline at end of file |
16 | |
17 | === modified file 'buildout-templates/bin/test.in' |
18 | --- buildout-templates/bin/test.in 2009-07-30 13:26:13 +0000 |
19 | +++ buildout-templates/bin/test.in 2009-08-10 22:08:05 +0000 |
20 | @@ -132,6 +132,7 @@ |
21 | pgsql.installFakeConnect() |
22 | |
23 | from zope.testing import testrunner |
24 | +from zope.testing.testrunner import options |
25 | |
26 | defaults = [ |
27 | # Find tests in the tests and ftests directories |
28 | @@ -188,24 +189,24 @@ |
29 | |
30 | def load_list(option, opt_str, list_name, parser): |
31 | patch_find_tests(filter_tests(list_name)) |
32 | - testrunner.parser.add_option( |
33 | + options.parser.add_option( |
34 | '--load-list', type=str, action='callback', callback=load_list) |
35 | |
36 | def list_test_option(option, opt, value, parser): |
37 | patch_find_tests(list_tests) |
38 | - testrunner.parser.add_option( |
39 | + options.parser.add_option( |
40 | '--list', action='callback', callback=list_test_option) |
41 | |
42 | def use_subunit(option, opt, value, parser): |
43 | patch_zope_testresult(TestProtocolClient(sys.stdout)) |
44 | - testrunner.parser.add_option( |
45 | + options.parser.add_option( |
46 | '--subunit', action='callback', callback=use_subunit) |
47 | |
48 | - options = testrunner.get_options(args=args, defaults=defaults) |
49 | + local_options = options.get_options(args=args, defaults=defaults) |
50 | |
51 | # Turn on Layer profiling if requested. |
52 | from canonical.testing import profiled |
53 | - if options.verbose >= 3 and main_process: |
54 | + if local_options.verbose >= 3 and main_process: |
55 | profiled.setup_profiling() |
56 | |
57 | # The working directory change is just so that the test script |
58 | @@ -222,6 +223,6 @@ |
59 | logging.disable(999999999) |
60 | |
61 | # Print Layer profiling report if requested. |
62 | - if main_process and options.verbose >= 3: |
63 | + if main_process and local_options.verbose >= 3: |
64 | profiled.report_profile_stats() |
65 | sys.exit(result) |
66 | |
67 | === modified file 'buildout.cfg' |
68 | --- buildout.cfg 2009-08-05 03:30:57 +0000 |
69 | +++ buildout.cfg 2009-08-05 19:05:57 +0000 |
70 | @@ -56,6 +56,12 @@ |
71 | initialization = import os |
72 | os.environ['STORM_CEXTENSIONS'] = '1' |
73 | os.environ.setdefault('LPCONFIG', '${configuration:instance_name}') |
74 | + # this can hopefully be removed when Twisted is used as an egg. |
75 | + import warnings |
76 | + warnings.filterwarnings( |
77 | + 'ignore', |
78 | + 'Module .+ was already imported from .+, but .+ is being added.*', |
79 | + UserWarning) |
80 | entry-points = stxdocs=zope.configuration.stxdocs:main |
81 | googletestservice=canonical.launchpad.testing.googletestservice:main |
82 | windmill=windmill.bin.windmill_bin:main |
83 | |
84 | === removed symlink 'lib/BTrees' |
85 | === target was u'../sourcecode/zope/src/BTrees/' |
86 | === removed symlink 'lib/ClientForm' |
87 | === target was u'../sourcecode/zope/src/ClientForm' |
88 | === removed symlink 'lib/RestrictedPython' |
89 | === target was u'../sourcecode/zope/src/RestrictedPython' |
90 | === removed symlink 'lib/ZConfig' |
91 | === target was u'../sourcecode/zope/src/ZConfig/' |
92 | === removed symlink 'lib/ZODB' |
93 | === target was u'../sourcecode/zope/src/ZODB/' |
94 | === modified file 'lib/canonical/config/__init__.py' |
95 | --- lib/canonical/config/__init__.py 2009-07-19 04:41:14 +0000 |
96 | +++ lib/canonical/config/__init__.py 2009-08-05 18:52:52 +0000 |
97 | @@ -16,6 +16,7 @@ |
98 | import sys |
99 | from urlparse import urlparse, urlunparse |
100 | |
101 | +import pkg_resources |
102 | import ZConfig |
103 | |
104 | from lazr.config import ImplicitTypeSchema |
105 | @@ -194,8 +195,10 @@ |
106 | |
107 | def _setZConfig(self): |
108 | """Modify the config, adding automatically generated settings""" |
109 | - schemafile = os.path.join( |
110 | - self.root, 'lib/zope/app/server/schema.xml') |
111 | + self.root = TREE_ROOT |
112 | + |
113 | + schemafile = pkg_resources.resource_filename( |
114 | + 'zope.app.server', 'schema.xml') |
115 | schema = ZConfig.loadSchema(schemafile) |
116 | root_options, handlers = ZConfig.loadConfig( |
117 | schema, self.zope_config_file) |
118 | |
119 | === modified file 'lib/canonical/config/tests/test_config.py' |
120 | --- lib/canonical/config/tests/test_config.py 2009-06-25 05:30:52 +0000 |
121 | +++ lib/canonical/config/tests/test_config.py 2009-08-05 18:52:52 +0000 |
122 | @@ -11,6 +11,7 @@ |
123 | |
124 | import ZConfig |
125 | import os |
126 | +import pkg_resources |
127 | import unittest |
128 | |
129 | from zope.testing.doctest import DocTestSuite, NORMALIZE_WHITESPACE, ELLIPSIS |
130 | @@ -20,11 +21,10 @@ |
131 | |
132 | # Calculate some landmark paths. |
133 | import canonical.config |
134 | +schema_file = pkg_resources.resource_filename('zope.app.server', 'schema.xml') |
135 | +schema = ZConfig.loadSchema(schema_file) |
136 | + |
137 | here = os.path.dirname(canonical.config.__file__) |
138 | -schema_file = os.path.join( |
139 | - here, os.pardir, os.pardir, 'zope/app/server/schema.xml') |
140 | -schema = ZConfig.loadSchema(schema_file) |
141 | - |
142 | lazr_schema_file = os.path.join(here, 'schema-lazr.conf') |
143 | |
144 | |
145 | |
146 | === modified file 'lib/canonical/configure.zcml' |
147 | --- lib/canonical/configure.zcml 2009-07-23 13:44:13 +0000 |
148 | +++ lib/canonical/configure.zcml 2009-08-13 15:22:00 +0000 |
149 | @@ -83,7 +83,7 @@ |
150 | virtual host layers. The directives come in pairs. |
151 | The separate registration for the resources namespace (@@) is needed |
152 | because otherwise the lookup for /@@/ will fail because the |
153 | - layer-specifif defaultView directive also registers the |
154 | + layer-specific defaultView directive also registers the |
155 | default view name as an unnamed adapter. |
156 | --> |
157 | --> |
158 | |
159 | === modified file 'lib/canonical/launchpad/browser/tests/registration.py' |
160 | --- lib/canonical/launchpad/browser/tests/registration.py 2009-06-25 05:30:52 +0000 |
161 | +++ lib/canonical/launchpad/browser/tests/registration.py 2009-08-05 18:52:52 +0000 |
162 | @@ -29,7 +29,7 @@ |
163 | |
164 | Return the Browser object after the registration is finished. |
165 | """ |
166 | - token_url = canonical_url(token) |
167 | + token_url = canonical_url(token).encode('utf8') |
168 | logout() |
169 | browser = setupBrowser() |
170 | browser.open(token_url) |
171 | |
172 | === modified file 'lib/canonical/launchpad/doc/announcement-date-widget.txt' |
173 | --- lib/canonical/launchpad/doc/announcement-date-widget.txt 2009-02-28 03:36:29 +0000 |
174 | +++ lib/canonical/launchpad/doc/announcement-date-widget.txt 2009-08-13 19:36:01 +0000 |
175 | @@ -59,7 +59,9 @@ |
176 | Traceback (most recent call last): |
177 | ... |
178 | WidgetInputError: ('field.foo', u'Foo', |
179 | - Please do not provide a date if you want to publish immediately.) |
180 | + LaunchpadValidationError(u'Please do not provide a date |
181 | + if you want to publish |
182 | + immediately.')) |
183 | |
184 | If you choose to publish at a specific date in the future, the date field |
185 | must be filled. |
186 | @@ -70,4 +72,4 @@ |
187 | Traceback (most recent call last): |
188 | ... |
189 | WidgetInputError: ('field.foo', u'Foo', |
190 | - Please provide a publication date.) |
191 | + LaunchpadValidationError(u'Please provide a publication date.')) |
192 | |
193 | === modified file 'lib/canonical/launchpad/doc/batch_navigation.txt' |
194 | --- lib/canonical/launchpad/doc/batch_navigation.txt 2009-03-24 12:43:49 +0000 |
195 | +++ lib/canonical/launchpad/doc/batch_navigation.txt 2009-08-06 11:02:58 +0000 |
196 | @@ -49,10 +49,13 @@ |
197 | This section demonstrates that batching generates sensible SQL queries when used |
198 | with SQLObject, i.e. that it puts appropriate LIMIT clauses on queries. |
199 | |
200 | -Imports: |
201 | +Imports and initialization: |
202 | |
203 | >>> from canonical.launchpad.database import EmailAddress |
204 | >>> from canonical.ftests.pgsql import CursorWrapper |
205 | + >>> from canonical.launchpad.interfaces import IStore |
206 | + >>> ignore = IStore(EmailAddress) # Prime the database connection. |
207 | + ... # (Priming is important if this test is run in isolation). |
208 | >>> CursorWrapper.record_sql = True |
209 | |
210 | Prepare a query, and create a batch of the results: |
211 | |
212 | === modified file 'lib/canonical/launchpad/doc/checkbox-matrix-widget.txt' |
213 | --- lib/canonical/launchpad/doc/checkbox-matrix-widget.txt 2008-09-22 22:09:40 +0000 |
214 | +++ lib/canonical/launchpad/doc/checkbox-matrix-widget.txt 2009-08-13 19:36:01 +0000 |
215 | @@ -24,16 +24,16 @@ |
216 | >>> matrix_widget._getFormValue() |
217 | [] |
218 | |
219 | -If we pass in a value via the request, we'll be able to get the licenses |
220 | +If we pass in a value via the request, we'll be able to get the licenses |
221 | as a set from _getFormValue() or getInputValue(): |
222 | |
223 | >>> request = LaunchpadTestRequest( |
224 | ... form={'field.licenses': ['GNU_LGPL_V2_1', 'GNU_GPL_V2']}) |
225 | >>> matrix_widget = CheckBoxMatrixWidget(licenses_field, vtype, request) |
226 | >>> matrix_widget._getFormValue() |
227 | - Set([<...License.GNU_GPL_V2...>, <...License.GNU_LGPL_V2_1...>]) |
228 | + set([<...License.GNU_GPL_V2...>, <...License.GNU_LGPL_V2_1...>]) |
229 | >>> matrix_widget.getInputValue() |
230 | - Set([<...License.GNU_GPL_V2...>, <...License.GNU_LGPL_V2_1...>]) |
231 | + set([<...License.GNU_GPL_V2...>, <...License.GNU_LGPL_V2_1...>]) |
232 | |
233 | It should render as many rows as are specified by the column_count attribute. |
234 | |
235 | |
236 | === modified file 'lib/canonical/launchpad/doc/feeds.txt' |
237 | --- lib/canonical/launchpad/doc/feeds.txt 2009-08-05 14:48:06 +0000 |
238 | +++ lib/canonical/launchpad/doc/feeds.txt 2009-08-05 18:52:52 +0000 |
239 | @@ -26,8 +26,8 @@ |
240 | >>> from zope.configuration import xmlconfig |
241 | >>> zcmlcontext = xmlconfig.string(""" |
242 | ... <configure xmlns:browser="http://namespaces.zope.org/browser"> |
243 | - ... <include file="lib/canonical/launchpad/webapp/meta.zcml" /> |
244 | - ... <include file="lib/zope/app/zcmlfiles/meta.zcml" /> |
245 | + ... <include package="canonical.launchpad.webapp" file="meta.zcml" /> |
246 | + ... <include package="zope.app.zcmlfiles" file="meta.zcml" /> |
247 | ... <browser:feeds |
248 | ... module="canonical.launchpad.ftests.feeds_helper" |
249 | ... classes="ThingFeedView" |
250 | |
251 | === modified file 'lib/canonical/launchpad/doc/image-widget.txt' |
252 | --- lib/canonical/launchpad/doc/image-widget.txt 2008-06-04 07:51:28 +0000 |
253 | +++ lib/canonical/launchpad/doc/image-widget.txt 2009-08-13 19:36:01 +0000 |
254 | @@ -2,8 +2,8 @@ |
255 | |
256 | In Launchpad we have images associated with people, products, distributions, |
257 | etc, and we want to allow people to have full control over their images. That |
258 | -is, they must be able to upload a new image and delete (or keep) an existing |
259 | -one. For this we created this widget, which can be embeded into any form we |
260 | +is, they must be able to upload a new image and delete (or keep) an existing |
261 | +one. For this we created this widget, which can be embeded into any form we |
262 | want, which doesn't require us to add any submit buttons to indicate that the |
263 | image should be kept, deleted or changed. |
264 | |
265 | @@ -170,7 +170,7 @@ |
266 | #=== The LogoTiedWithMugshotWidget === |
267 | # |
268 | #This is a specialized version of the ImageChangeWidget which also returns a |
269 | -#resized version of the uploaded image, in case one was uploaded. |
270 | +#resized version of the uploaded image, in case one was uploaded. |
271 | # |
272 | # >>> from canonical.widgets.image import LogoTiedWithMugshotWidget |
273 | # >>> mugshot_file_name = os.path.join( |
274 | @@ -385,7 +385,8 @@ |
275 | Traceback (most recent call last): |
276 | ... |
277 | WidgetInputError: ('field.mugshot', u'Mugshot', |
278 | - This image is not exactly 192x192 pixels in size.) |
279 | + LaunchpadValidationError(u'\nThis image is not exactly |
280 | + 192x192\npixels in size.')) |
281 | |
282 | |
283 | This is what we see when the image is the correct dimensions, and within the |
284 | @@ -429,7 +430,9 @@ |
285 | Traceback (most recent call last): |
286 | ... |
287 | WidgetInputError: ('field.mugshot', u'Mugshot', |
288 | - This image exceeds the maximum allowed size in bytes.) |
289 | + LaunchpadValidationError(u'\nThis image exceeds the |
290 | + maximum allowed size in |
291 | + bytes.')) |
292 | |
293 | A similar error will be raised if the image's dimensions are bigger than the |
294 | maximum we allow. |
295 | @@ -443,7 +446,8 @@ |
296 | Traceback (most recent call last): |
297 | ... |
298 | WidgetInputError: ('field.mugshot', u'Mugshot', |
299 | - This image is not exactly 191x193 pixels in size.) |
300 | + LaunchpadValidationError(u'\nThis image is not exactly |
301 | + 191x193\npixels in size.')) |
302 | |
303 | >>> person_mugshot.dimensions = (image.size[0] + 1, image.size[1] - 1) |
304 | >>> mugshot.seek(0) |
305 | @@ -453,7 +457,8 @@ |
306 | Traceback (most recent call last): |
307 | ... |
308 | WidgetInputError: ('field.mugshot', u'Mugshot', |
309 | - This image is not exactly 193x191 pixels in size.) |
310 | + LaunchpadValidationError(u'\nThis image is not exactly |
311 | + 193x191\npixels in size.')) |
312 | |
313 | We also won't accept anything that is not an image; that is, we only accept |
314 | what can be parsed by the Python Imaging Library module. |
315 | @@ -468,8 +473,10 @@ |
316 | Traceback (most recent call last): |
317 | ... |
318 | WidgetInputError: ('field.mugshot', u'Mugshot', |
319 | - The file uploaded was not recognized as an image; |
320 | - please check it and retry.) |
321 | + LaunchpadValidationError(u'\nThe file uploaded was not |
322 | + recognized as an image; |
323 | + please\ncheck it and |
324 | + retry.')) |
325 | |
326 | Finally, if the user specifies the 'change' action he must also provide a file |
327 | to be uploaded. |
328 | @@ -481,7 +488,8 @@ |
329 | Traceback (most recent call last): |
330 | ... |
331 | WidgetInputError: ('field.mugshot', u'Mugshot', |
332 | - Please specify the image you want to use.) |
333 | + LaunchpadValidationError(u'Please specify the image you |
334 | + want to use.')) |
335 | |
336 | |
337 | == Non-exact Image Dimensions == |
338 | @@ -503,7 +511,8 @@ |
339 | Traceback (most recent call last): |
340 | ... |
341 | WidgetInputError: ('field.mugshot', u'Mugshot', |
342 | - This image is larger than 64x64 pixels in size.) |
343 | + LaunchpadValidationError(u'\nThis image is larger than |
344 | + 64x64\npixels in size.')) |
345 | |
346 | If the image is smaller than the dimensions, the input validates: |
347 | |
348 | @@ -524,4 +533,3 @@ |
349 | >>> fileupload = widget.getInputValue() |
350 | >>> fileupload.filename |
351 | u'mugshot.png' |
352 | - |
353 | |
354 | === modified file 'lib/canonical/launchpad/doc/launchpadlib.txt' |
355 | --- lib/canonical/launchpad/doc/launchpadlib.txt 2008-05-22 19:11:05 +0000 |
356 | +++ lib/canonical/launchpad/doc/launchpadlib.txt 2009-06-11 01:28:55 +0000 |
357 | @@ -11,7 +11,7 @@ |
358 | >>> browser.open('http://launchpad.dev:8085/~stimpy') |
359 | Traceback (most recent call last): |
360 | ... |
361 | - HTTPError: HTTP Error 404: Not Found |
362 | + httperror_seek_wrapper: HTTP Error 404: Not Found |
363 | |
364 | ...and when he doesn't, create him. |
365 | |
366 | |
367 | === modified file 'lib/canonical/launchpad/doc/loginstatus-pages.txt' |
368 | --- lib/canonical/launchpad/doc/loginstatus-pages.txt 2009-04-17 10:32:16 +0000 |
369 | +++ lib/canonical/launchpad/doc/loginstatus-pages.txt 2009-08-13 13:33:26 +0000 |
370 | @@ -112,7 +112,7 @@ |
371 | |
372 | >>> print view() |
373 | <... |
374 | - ...<a href="http://launchpad.dev/~name16"...>... |
375 | + ...<a href="/~name16"...>... |
376 | |
377 | The link is for the user's Profile page in the 'overview' facet, even if |
378 | we are viewing the 'bugs' facet. |
379 | |
380 | === modified file 'lib/canonical/launchpad/doc/navigation.txt' |
381 | --- lib/canonical/launchpad/doc/navigation.txt 2008-09-30 22:25:04 +0000 |
382 | +++ lib/canonical/launchpad/doc/navigation.txt 2009-06-11 01:28:55 +0000 |
383 | @@ -249,8 +249,8 @@ |
384 | >>> from zope.configuration import xmlconfig |
385 | >>> zcmlcontext = xmlconfig.string(""" |
386 | ... <configure xmlns:browser="http://namespaces.zope.org/browser"> |
387 | - ... <include file="lib/canonical/launchpad/webapp/meta.zcml" /> |
388 | - ... <include file="lib/zope/app/zcmlfiles/meta.zcml" /> |
389 | + ... <include package="canonical.launchpad.webapp" file="meta.zcml" /> |
390 | + ... <include package="zope.app.zcmlfiles" file="meta.zcml" /> |
391 | ... <browser:navigation |
392 | ... module="canonical.launchpad.ftests" |
393 | ... classes="ThingSetNavigation" |
394 | |
395 | === modified file 'lib/canonical/launchpad/doc/renamed-view.txt' |
396 | --- lib/canonical/launchpad/doc/renamed-view.txt 2008-09-30 22:25:04 +0000 |
397 | +++ lib/canonical/launchpad/doc/renamed-view.txt 2009-06-11 01:28:55 +0000 |
398 | @@ -100,8 +100,8 @@ |
399 | >>> from zope.configuration import xmlconfig |
400 | >>> zcmlcontext = xmlconfig.string(""" |
401 | ... <configure xmlns:browser="http://namespaces.zope.org/browser"> |
402 | - ... <include file="lib/canonical/launchpad/webapp/meta.zcml" /> |
403 | - ... <include file="lib/zope/app/zcmlfiles/meta.zcml" /> |
404 | + ... <include package="canonical.launchpad.webapp" file="meta.zcml" /> |
405 | + ... <include package="zope.app.zcmlfiles" file="meta.zcml" /> |
406 | ... <browser:renamed-page |
407 | ... for="canonical.launchpad.interfaces.IQuestionTarget" |
408 | ... name="+old_tickets_page" |
409 | |
410 | === modified file 'lib/canonical/launchpad/doc/storm.txt' |
411 | --- lib/canonical/launchpad/doc/storm.txt 2009-07-24 12:55:03 +0000 |
412 | +++ lib/canonical/launchpad/doc/storm.txt 2009-08-05 18:52:52 +0000 |
413 | @@ -83,6 +83,7 @@ |
414 | ... |
415 | InternalError: transaction is read-only |
416 | |
417 | + >>> transaction.abort() |
418 | >>> t = transaction.begin() |
419 | >>> account = auth_slave.find( |
420 | ... Account, openid_identifier='sabdfl_oid').one() |
421 | |
422 | === modified file 'lib/canonical/launchpad/doc/stripped-text-widget.txt' |
423 | --- lib/canonical/launchpad/doc/stripped-text-widget.txt 2007-06-17 11:57:02 +0000 |
424 | +++ lib/canonical/launchpad/doc/stripped-text-widget.txt 2009-08-13 19:36:01 +0000 |
425 | @@ -38,4 +38,4 @@ |
426 | >>> widget.getInputValue() |
427 | Traceback (most recent call last): |
428 | ... |
429 | - WidgetInputError: ('field', u'Title', ) |
430 | + WidgetInputError: ('field', u'Title', RequiredMissing()) |
431 | |
432 | === modified file 'lib/canonical/launchpad/doc/tales.txt' |
433 | --- lib/canonical/launchpad/doc/tales.txt 2009-08-11 07:20:12 +0000 |
434 | +++ lib/canonical/launchpad/doc/tales.txt 2009-08-13 21:32:59 +0000 |
435 | @@ -268,11 +268,11 @@ |
436 | >>> print test_tales("bug/fmt:url/+text", bug=bug) |
437 | http://bugs.launchpad.dev/bugs/1/+text |
438 | |
439 | - # Undo the custom setup we did above. |
440 | - |
441 | - >>> login(ANONYMOUS) |
442 | - |
443 | -Persons and teams can also specify an alternate rootsite to fmt:url. |
444 | + |
445 | +fmt:url accepts an rootsite extension to make URLs to a specific application. |
446 | + |
447 | + >>> login(ANONYMOUS, |
448 | + ... LaunchpadTestRequest(SERVER_URL='http://code.launchpad.net')) |
449 | |
450 | >>> print test_tales("person/fmt:url:bugs", person=sabdfl) |
451 | http://bugs.launchpad.dev/~sabdfl |
452 | @@ -280,6 +280,14 @@ |
453 | >>> print test_tales("person/fmt:url:feeds", person=sabdfl) |
454 | http://feeds.launchpad.dev/~sabdfl |
455 | |
456 | + >>> print test_tales("pillar/fmt:url:answers", pillar=ubuntu) |
457 | + http://answers.launchpad.dev/ubuntu |
458 | + |
459 | + >>> print test_tales("bug/fmt:url:mainsite", bug=bug) |
460 | + http://launchpad.dev/bugs/1 |
461 | + |
462 | + >>> login(ANONYMOUS) |
463 | + |
464 | |
465 | The fmt: namespace to get links |
466 | ------------------------------- |
467 | @@ -319,6 +327,34 @@ |
468 | >>> test_tales("person/fmt:link", person=ubuntu_team) |
469 | u'<a href=".../~ubuntu-team" class="sprite team">Ubuntu Team</a>' |
470 | |
471 | +The link can make the URL go to a specific app. |
472 | + |
473 | + >>> login(ANONYMOUS, |
474 | + ... LaunchpadTestRequest(SERVER_URL='http://code.launchpad.net')) |
475 | + |
476 | + >>> print test_tales("pillar/fmt:link:translations", pillar=ubuntu) |
477 | + <a ...http://translations.launchpad.dev/ubuntu... |
478 | + |
479 | + >>> print test_tales("person/fmt:url:feeds", person=sabdfl) |
480 | + http://feeds.launchpad.dev/~sabdfl |
481 | + |
482 | + >>> print test_tales("bug/fmt:url:mainsite", bug=bug) |
483 | + http://launchpad.dev/bugs/1 |
484 | + |
485 | +The default behaviour for pillars, persons, and teams is to link to |
486 | +the mainsite. |
487 | + |
488 | + >>> print test_tales("pillar/fmt:link", pillar=ubuntu) |
489 | + <a ...http://launchpad.dev/ubuntu... |
490 | + |
491 | + >>> print test_tales("person/fmt:link", person=sabdfl) |
492 | + <a ...http://launchpad.dev/~sabdfl... |
493 | + |
494 | + >>> print test_tales("team/fmt:link", team=ubuntu_team) |
495 | + <a ...http://launchpad.dev/~ubuntu-team... |
496 | + |
497 | + >>> login(ANONYMOUS) |
498 | + |
499 | The person's displayname is escaped to prevent markup from being |
500 | interpreted by the browser. For example, a script added to Sample |
501 | Person's displayname will be escaped; averting a XSS vulnerability. |
502 | |
503 | === modified file 'lib/canonical/launchpad/ftests/feeds_helper.py' |
504 | --- lib/canonical/launchpad/ftests/feeds_helper.py 2009-06-25 05:30:52 +0000 |
505 | +++ lib/canonical/launchpad/ftests/feeds_helper.py 2009-08-05 18:52:52 +0000 |
506 | @@ -15,9 +15,13 @@ |
507 | ] |
508 | |
509 | |
510 | +import socket |
511 | +original_timeout = socket.getdefaulttimeout() |
512 | import feedvalidator |
513 | +if socket.getdefaulttimeout() != original_timeout: |
514 | + # feedvalidator's __init__ uses setdefaulttimeout promiscuously |
515 | + socket.setdefaulttimeout(original_timeout) |
516 | from cStringIO import StringIO |
517 | -import socket |
518 | from textwrap import wrap |
519 | |
520 | from zope.interface import implements, Interface, Attribute |
521 | |
522 | === modified file 'lib/canonical/launchpad/icing/style-3-0.css' |
523 | --- lib/canonical/launchpad/icing/style-3-0.css 2009-08-07 14:01:57 +0000 |
524 | +++ lib/canonical/launchpad/icing/style-3-0.css 2009-08-13 02:24:56 +0000 |
525 | @@ -179,7 +179,16 @@ |
526 | #colophon { |
527 | float: none; |
528 | } |
529 | +#globalsearch { |
530 | + float: none; |
531 | + display: auto; |
532 | + font-weight: inherit; |
533 | + margin-right: auto; |
534 | +} |
535 | |
536 | +#globalsearch input { |
537 | + font-size: inherit; |
538 | +} |
539 | |
540 | /* Page layout */ |
541 | .yui-d0 { |
542 | @@ -195,9 +204,25 @@ |
543 | .footer { |
544 | clear: both; |
545 | margin-top: 2em; |
546 | - border-top: 1px solid #cdd3dd; |
547 | padding-top: 0.5em; |
548 | } |
549 | +.footer .lp-arcana { |
550 | + background: url(/@@/footer-background.png) top left repeat-x; |
551 | + padding: 0.8em; |
552 | + -moz-border-radius: 3px 3px 0 0; |
553 | + -webkit-border-radius: 3px 3px 0 0; |
554 | + border-radius: 3px 3px 0 0; |
555 | + } |
556 | +.footer .lp-arcana img { |
557 | + vertical-align: middle; |
558 | + } |
559 | +.footer .lp-arcana .search-icon { |
560 | + background: url(icon-sprites) 100% -191px no-repeat; |
561 | + } |
562 | +.footer .colophon { |
563 | + margin: 3em 3em 1em 3em; |
564 | + text-align: center; |
565 | + } |
566 | .portlet, .aside { |
567 | clear: both; |
568 | border-top: 1px solid #d6d6d6; |
569 | @@ -424,7 +449,7 @@ |
570 | /* The text of the first tab should align with the heading directly |
571 | above it */ |
572 | .location-portlet li:first-child a, .location-portlet li:first-child span { |
573 | - margin-left: -0.5em; |
574 | + margin-left: -0.5em; |
575 | } |
576 | .location-portlet li a:link, .location-portlet li a:visited { |
577 | color: #000; |
578 | |
579 | === modified file 'lib/canonical/launchpad/icing/style.css' |
580 | --- lib/canonical/launchpad/icing/style.css 2009-08-05 08:15:28 +0000 |
581 | +++ lib/canonical/launchpad/icing/style.css 2009-08-12 21:08:05 +0000 |
582 | @@ -71,6 +71,7 @@ |
583 | .info {background:url(icon-sprites) 0 -96px no-repeat;} |
584 | .question {background:url(icon-sprites) 0 -128px no-repeat;} |
585 | .download-icon {background:url(icon-sprites) 0 -160px no-repeat;} |
586 | +.download {background:url(icon-sprites) 0 -160px no-repeat;} |
587 | .search-icon {background:url(icon-sprites) 0 -187px no-repeat;} |
588 | .no {background:url(icon-sprites) 0 -224px no-repeat;} |
589 | .yes {background:url(icon-sprites) 0 -256px no-repeat;} |
590 | |
591 | === added file 'lib/canonical/launchpad/images/footer-background.png' |
592 | Binary files lib/canonical/launchpad/images/footer-background.png 1970-01-01 00:00:00 +0000 and lib/canonical/launchpad/images/footer-background.png 2009-08-13 01:01:39 +0000 differ |
593 | === modified file 'lib/canonical/launchpad/pagetests/basics/max-batch-size.txt' |
594 | --- lib/canonical/launchpad/pagetests/basics/max-batch-size.txt 2009-07-17 14:00:36 +0000 |
595 | +++ lib/canonical/launchpad/pagetests/basics/max-batch-size.txt 2009-08-05 18:52:52 +0000 |
596 | @@ -10,7 +10,7 @@ |
597 | >>> anon_browser.open('http://launchpad.dev/projects/+all?start=0&batch=1000') |
598 | Traceback (most recent call last): |
599 | ... |
600 | - HTTPError: HTTP Error 400: Bad Request |
601 | + httperror_seek_wrapper: HTTP Error 400: Bad Request |
602 | |
603 | >>> print extract_text(find_main_content(anon_browser.contents)) |
604 | Invalid Batch Size |
605 | |
606 | === modified file 'lib/canonical/launchpad/pagetests/feeds/xx-authentication.txt' |
607 | --- lib/canonical/launchpad/pagetests/feeds/xx-authentication.txt 2008-01-31 23:21:01 +0000 |
608 | +++ lib/canonical/launchpad/pagetests/feeds/xx-authentication.txt 2009-07-16 13:28:25 +0000 |
609 | @@ -23,4 +23,4 @@ |
610 | >>> browser.open('http://feeds.launchpad.dev/bugs/14/bug.atom') |
611 | Traceback (most recent call last): |
612 | ... |
613 | - HTTPError: HTTP Error 403: Forbidden |
614 | + httperror_seek_wrapper: HTTP Error 403: Forbidden |
615 | |
616 | === modified file 'lib/canonical/launchpad/pagetests/oauth/access-token.txt' |
617 | --- lib/canonical/launchpad/pagetests/oauth/access-token.txt 2008-07-22 20:34:14 +0000 |
618 | +++ lib/canonical/launchpad/pagetests/oauth/access-token.txt 2009-07-16 13:28:25 +0000 |
619 | @@ -40,7 +40,7 @@ |
620 | ... 'http://launchpad.dev/+access-token', data=urlencode(data)) |
621 | Traceback (most recent call last): |
622 | ... |
623 | - HTTPError: HTTP Error 401: Unauthorized |
624 | + httperror_seek_wrapper: HTTP Error 401: Unauthorized |
625 | |
626 | The token's context, when not None, is sent to the consumer together |
627 | with the token's key and secret. |
628 | |
629 | === modified file 'lib/canonical/launchpad/pagetests/standalone/xx-beta-testers-redirection.txt' |
630 | --- lib/canonical/launchpad/pagetests/standalone/xx-beta-testers-redirection.txt 2009-05-12 16:29:13 +0000 |
631 | +++ lib/canonical/launchpad/pagetests/standalone/xx-beta-testers-redirection.txt 2009-08-06 11:35:34 +0000 |
632 | @@ -27,7 +27,7 @@ |
633 | ... function(*args, **kwargs) |
634 | ... except HTTPError, exc: |
635 | ... print str(exc) |
636 | - ... location = exc.headers.getheader('Location') |
637 | + ... location = exc.hdrs.getheader('Location') |
638 | ... if location is not None: |
639 | ... print 'Location:', location |
640 | |
641 | |
642 | === modified file 'lib/canonical/launchpad/scripts/ftests/test_oops_prune.py' |
643 | --- lib/canonical/launchpad/scripts/ftests/test_oops_prune.py 2009-06-25 05:30:52 +0000 |
644 | +++ lib/canonical/launchpad/scripts/ftests/test_oops_prune.py 2009-08-07 12:46:37 +0000 |
645 | @@ -58,9 +58,12 @@ |
646 | INSERT INTO MessageChunk(message, sequence, content) |
647 | VALUES (1, 99, 'OOPS-%s') |
648 | """ % self.referenced_oops_code) |
649 | + if not os.path.exists(config.error_reports.error_dir): |
650 | + os.mkdir(config.error_reports.error_dir) |
651 | |
652 | def tearDown(self): |
653 | shutil.rmtree(self.oops_dir) |
654 | + shutil.rmtree(config.error_reports.error_dir) |
655 | |
656 | def test_referenced_oops(self): |
657 | self.failUnlessEqual( |
658 | |
659 | === modified file 'lib/canonical/launchpad/webapp/ftests/test_adapter_permissions.txt' |
660 | --- lib/canonical/launchpad/webapp/ftests/test_adapter_permissions.txt 2009-04-02 16:39:20 +0000 |
661 | +++ lib/canonical/launchpad/webapp/ftests/test_adapter_permissions.txt 2009-06-11 01:28:55 +0000 |
662 | @@ -28,6 +28,7 @@ |
663 | |
664 | Test this once more to ensure the settings stick across transactions. |
665 | |
666 | + >>> transaction.abort() |
667 | >>> t = transaction.begin() |
668 | >>> main_slave.find(Person, name='janitor').one().displayname = 'BenD' |
669 | >>> transaction.commit() |
670 | |
671 | === modified file 'lib/canonical/launchpad/webapp/tales.py' |
672 | --- lib/canonical/launchpad/webapp/tales.py 2009-08-13 00:51:50 +0000 |
673 | +++ lib/canonical/launchpad/webapp/tales.py 2009-08-14 12:56:19 +0000 |
674 | @@ -458,7 +458,25 @@ |
675 | return self.url() |
676 | |
677 | def traverse(self, name, furtherPath): |
678 | - if name in self.traversable_names: |
679 | + if name.startswith('link:') or name.startswith('url:'): |
680 | + rootsite = name.split(':')[1] |
681 | + extra_path = None |
682 | + if len(furtherPath) > 0: |
683 | + extra_path = '/'.join(reversed(furtherPath)) |
684 | + # Remove remaining entries in furtherPath so that traversal |
685 | + # stops here. |
686 | + del furtherPath[:] |
687 | + if name.startswith('link:'): |
688 | + if rootsite is None: |
689 | + return self.link(extra_path) |
690 | + else: |
691 | + return self.link(extra_path, rootsite=rootsite) |
692 | + else: |
693 | + if rootsite is None: |
694 | + self.url(extra_path) |
695 | + else: |
696 | + return self.url(extra_path, rootsite=rootsite) |
697 | + elif name in self.traversable_names: |
698 | if len(furtherPath) >= 1: |
699 | extra_path = '/'.join(reversed(furtherPath)) |
700 | del furtherPath[:] |
701 | @@ -472,13 +490,16 @@ |
702 | else: |
703 | raise TraversalError, name |
704 | |
705 | - def link(self, view_name): |
706 | + def link(self, view_name, rootsite=None): |
707 | """Return an HTML link to the object's page. |
708 | |
709 | The link consists of an icon followed by the object's name. |
710 | |
711 | :param view_name: If not None, the link will point to the page with |
712 | that name on this object. |
713 | + :param rootsite: If not None, return the URL to the page on the |
714 | + specified rootsite. Note this is available only for subclasses |
715 | + that allow specifying the rootsite. |
716 | """ |
717 | raise NotImplementedError( |
718 | "No link implementation for %r, IPathAdapter implementation " |
719 | @@ -958,23 +979,6 @@ |
720 | final_traversable_names = {'local-time': 'local_time'} |
721 | final_traversable_names.update(ObjectFormatterAPI.final_traversable_names) |
722 | |
723 | - def traverse(self, name, furtherPath): |
724 | - """Special-case traversal for links with an optional rootsite.""" |
725 | - if name.startswith('link:') or name.startswith('url:'): |
726 | - rootsite = name.split(':')[1] |
727 | - extra_path = None |
728 | - if len(furtherPath) > 0: |
729 | - extra_path = '/'.join(reversed(furtherPath)) |
730 | - # Remove remaining entries in furtherPath so that traversal |
731 | - # stops here. |
732 | - del furtherPath[:] |
733 | - if name.startswith('link:'): |
734 | - return self.link(extra_path, rootsite=rootsite) |
735 | - else: |
736 | - return self.url(extra_path, rootsite=rootsite) |
737 | - else: |
738 | - return super(PersonFormatterAPI, self).traverse(name, furtherPath) |
739 | - |
740 | def local_time(self): |
741 | """Return the local time for this person.""" |
742 | time_zone = 'UTC' |
743 | @@ -982,12 +986,22 @@ |
744 | time_zone = self._context.time_zone |
745 | return datetime.now(pytz.timezone(time_zone)).strftime('%T %Z') |
746 | |
747 | - def link(self, view_name, rootsite=None): |
748 | - """Return an HTML link to the person's page containing an icon |
749 | - followed by the person's name. |
750 | + def url(self, view_name=None, rootsite='mainsite'): |
751 | + """See `ObjectFormatterAPI`. |
752 | + |
753 | + The default URL for a person is to the mainsite. |
754 | + """ |
755 | + return super(PersonFormatterAPI, self).url(view_name, rootsite) |
756 | + |
757 | + def link(self, view_name, rootsite='mainsite'): |
758 | + """See `ObjectFormatterAPI`. |
759 | + |
760 | + Return an HTML link to the person's page containing an icon |
761 | + followed by the person's name. The default URL for a person is to |
762 | + the mainsite. |
763 | """ |
764 | person = self._context |
765 | - url = canonical_url(person, rootsite=rootsite, view_name=view_name) |
766 | + url = self.url(view_name, rootsite) |
767 | custom_icon = ObjectImageDisplayAPI(person)._get_custom_icon_url() |
768 | if custom_icon is None: |
769 | css_class = ObjectImageDisplayAPI(person).sprite_css() |
770 | @@ -1024,12 +1038,16 @@ |
771 | |
772 | hidden = u'<hidden>' |
773 | |
774 | - def url(self, view_name=None): |
775 | - """See `ObjectFormatterAPI`.""" |
776 | + def url(self, view_name=None, rootsite='mainsite'): |
777 | + """See `ObjectFormatterAPI`. |
778 | + |
779 | + The default URL for a team is to the mainsite. None is returned |
780 | + when the user does not have permission to review the team. |
781 | + """ |
782 | if not check_permission('launchpad.View', self._context): |
783 | # This person has no permission to view the team details. |
784 | return None |
785 | - return super(TeamFormatterAPI, self).url(view_name) |
786 | + return super(TeamFormatterAPI, self).url(view_name, rootsite) |
787 | |
788 | def api_url(self, context): |
789 | """See `ObjectFormatterAPI`.""" |
790 | @@ -1038,8 +1056,12 @@ |
791 | return None |
792 | return super(TeamFormatterAPI, self).api_url(context) |
793 | |
794 | - def link(self, view_name, rootsite=None): |
795 | - """See `ObjectFormatterAPI`.""" |
796 | + def link(self, view_name, rootsite='mainsite'): |
797 | + """See `ObjectFormatterAPI`. |
798 | + |
799 | + The default URL for a team is to the mainsite. None is returned |
800 | + when the user does not have permission to review the team. |
801 | + """ |
802 | person = self._context |
803 | if not check_permission('launchpad.View', person): |
804 | # This person has no permission to view the team details. |
805 | @@ -1116,7 +1138,7 @@ |
806 | """ |
807 | return queryAdapter(self._context, IPathAdapter, 'image').sprite_css() |
808 | |
809 | - def link(self, view_name): |
810 | + def link(self, view_name, rootsite=None): |
811 | """Return html including a link, description and icon. |
812 | |
813 | Icon and link are optional, depending on type and permissions. |
814 | @@ -1132,7 +1154,7 @@ |
815 | |
816 | summary = self._make_link_summary() |
817 | if check_permission(self._link_permission, self._context): |
818 | - url = self.url(view_name) |
819 | + url = self.url(view_name, rootsite) |
820 | else: |
821 | url = '' |
822 | if url: |
823 | @@ -1152,33 +1174,40 @@ |
824 | displayname = self._context.displayname |
825 | return {'displayname': displayname} |
826 | |
827 | - def link(self, view_name): |
828 | + def url(self, view_name=None, rootsite=None): |
829 | + """See `ObjectFormatterAPI`. |
830 | + |
831 | + The default URL for a pillar is to the mainsite. |
832 | + """ |
833 | + return super(PillarFormatterAPI, self).url(view_name, rootsite) |
834 | + |
835 | + def link(self, view_name, rootsite='mainsite'): |
836 | """The html to show a link to a Product, Project or distribution. |
837 | |
838 | In the case of Products or Project groups we display the custom |
839 | - icon, if one exists.""" |
840 | + icon, if one exists. The default URL for a pillar is to the mainsite. |
841 | + """ |
842 | |
843 | html = super(PillarFormatterAPI, self).link(view_name) |
844 | context = self._context |
845 | - if IProduct.providedBy(context) or IProject.providedBy(context): |
846 | - custom_icon = ObjectImageDisplayAPI( |
847 | - context)._get_custom_icon_url() |
848 | - url = canonical_url(context, view_name=view_name) |
849 | - summary = self._make_link_summary() |
850 | - if custom_icon is None: |
851 | - css_class = ObjectImageDisplayAPI(context).sprite_css() |
852 | - html = (u'<a href="%s" class="%s">%s</a>') % ( |
853 | - url, css_class, summary) |
854 | - else: |
855 | - html = (u'<a href="%s" class="bg-image" ' |
856 | - 'style="background-image: url(%s)">%s</a>') % ( |
857 | - url, custom_icon, summary) |
858 | - if IProduct.providedBy(context): |
859 | - license_status = context.license_status |
860 | - if license_status != LicenseStatus.OPEN_SOURCE: |
861 | - html = '<span title="%s">%s (%s)</span>' % ( |
862 | - license_status.description, html, |
863 | - license_status.title) |
864 | + custom_icon = ObjectImageDisplayAPI( |
865 | + context)._get_custom_icon_url() |
866 | + url = self.url(view_name, rootsite) |
867 | + summary = self._make_link_summary() |
868 | + if custom_icon is None: |
869 | + css_class = ObjectImageDisplayAPI(context).sprite_css() |
870 | + html = (u'<a href="%s" class="%s">%s</a>') % ( |
871 | + url, css_class, summary) |
872 | + else: |
873 | + html = (u'<a href="%s" class="bg-image" ' |
874 | + 'style="background-image: url(%s)">%s</a>') % ( |
875 | + url, custom_icon, summary) |
876 | + if IProduct.providedBy(context): |
877 | + license_status = context.license_status |
878 | + if license_status != LicenseStatus.OPEN_SOURCE: |
879 | + html = '<span title="%s">%s (%s)</span>' % ( |
880 | + license_status.description, html, |
881 | + license_status.title) |
882 | return html |
883 | |
884 | |
885 | @@ -1231,7 +1260,7 @@ |
886 | html += ')' |
887 | return html % replacements |
888 | |
889 | - def url(self, view_name): |
890 | + def url(self, view_name, rootsite=None): |
891 | """Return the URL to download the file.""" |
892 | return self._getDownloadURL(self._context.libraryfile) |
893 | |
894 | @@ -1294,7 +1323,7 @@ |
895 | class PreviewDiffFormatterAPI(ObjectFormatterAPI): |
896 | """Formatter for preview diffs.""" |
897 | |
898 | - def url(self, view_name=None): |
899 | + def url(self, view_name=None, rootsite=None): |
900 | """Use the url of the librarian file containing the diff. |
901 | """ |
902 | librarian_alias = self._context.diff_text |
903 | @@ -1423,7 +1452,7 @@ |
904 | 'branch': self._context.branch.bzr_identity, |
905 | } |
906 | |
907 | - def url(self, view_name=None): |
908 | + def url(self, view_name=None, rootsite=None): |
909 | """See `ObjectFormatterAPI`.""" |
910 | # The url of a code import is the associated branch. |
911 | # This is still here primarily for supporting branch deletion, |
912 | @@ -2064,7 +2093,7 @@ |
913 | """Return the default representation of the link.""" |
914 | return self._context.render() |
915 | |
916 | - def url(self, view_name=None): |
917 | + def url(self, view_name=None, rootsite=None): |
918 | """Return the URL representation of the link.""" |
919 | if self._context.enabled: |
920 | return self._context.url |
921 | |
922 | === modified file 'lib/canonical/testing/__init__.py' |
923 | --- lib/canonical/testing/__init__.py 2009-07-17 18:46:25 +0000 |
924 | +++ lib/canonical/testing/__init__.py 2009-08-10 22:08:05 +0000 |
925 | @@ -63,8 +63,9 @@ |
926 | logging._handlers.clear() |
927 | |
928 | # Reset the setup |
929 | - import zope.testing.testrunner |
930 | - zope.testing.testrunner.configure_logging() |
931 | + from zope.testing.testrunner.runner import Runner |
932 | + from zope.testing.testrunner.logsupport import Logging |
933 | + Logging(Runner()).global_setup() |
934 | |
935 | |
936 | # This import registers the 'doctest' Unicode codec. |
937 | |
938 | === modified file 'lib/canonical/testing/ftests/test_mockdb.py' |
939 | --- lib/canonical/testing/ftests/test_mockdb.py 2009-06-25 05:30:52 +0000 |
940 | +++ lib/canonical/testing/ftests/test_mockdb.py 2009-08-05 18:52:52 +0000 |
941 | @@ -11,7 +11,7 @@ |
942 | import unittest |
943 | |
944 | import psycopg2 |
945 | -from zope.testing.testrunner import dont_retry, RetryTest |
946 | +# from zope.testing.testrunner import dont_retry, RetryTest |
947 | |
948 | from canonical.config import config |
949 | from canonical.testing import mockdb, DatabaseLayer |
950 | @@ -101,63 +101,63 @@ |
951 | self.connections.append(con) |
952 | return con |
953 | |
954 | - @dont_retry |
955 | - def testIncorrectReplay(self): |
956 | - # Record nothing but a close on a single connection. |
957 | - con = self.connect() |
958 | - con.close() |
959 | - self.script.store() |
960 | - |
961 | - # Replay correctly. |
962 | - self.switchToReplayMode() |
963 | - con = self.connect() |
964 | - con.close() |
965 | - |
966 | - # Replay incorrectly. |
967 | - self.switchToReplayMode() |
968 | - con = self.connect() |
969 | - self.assertRaises(RetryTest, con.rollback) |
970 | - |
971 | - @dont_retry |
972 | - def testMultipleConnections(self): |
973 | + # @dont_retry |
974 | + #def testIncorrectReplay(self): |
975 | + # # Record nothing but a close on a single connection. |
976 | + # con = self.connect() |
977 | + # con.close() |
978 | + # self.script.store() |
979 | + |
980 | + # # Replay correctly. |
981 | + # self.switchToReplayMode() |
982 | + # con = self.connect() |
983 | + # con.close() |
984 | + |
985 | + # # Replay incorrectly. |
986 | + # self.switchToReplayMode() |
987 | + # con = self.connect() |
988 | + # self.assertRaises(RetryTest, con.rollback) |
989 | + |
990 | + # @dont_retry |
991 | + #def testMultipleConnections(self): |
992 | # Ensure that commands issued via different connections |
993 | # maintain their global order. |
994 | - con1 = self.connect() |
995 | - con2 = self.connect() |
996 | - con1.close() |
997 | - con2.close() |
998 | - self.script.store() |
999 | - |
1000 | - # Replay correctly. |
1001 | - self.switchToReplayMode() |
1002 | - con1 = self.connect() |
1003 | - con2 = self.connect() |
1004 | - con1.close() |
1005 | - con2.close() |
1006 | - |
1007 | - # Replay in the wrong order. |
1008 | - self.switchToReplayMode() |
1009 | - con1 = self.connect() |
1010 | - con2 = self.connect() |
1011 | - self.assertRaises(RetryTest, con2.close) |
1012 | - |
1013 | - @dont_retry |
1014 | - def testConnectionParams(self): |
1015 | + # con1 = self.connect() |
1016 | + # con2 = self.connect() |
1017 | + # con1.close() |
1018 | + # con2.close() |
1019 | + # self.script.store() |
1020 | + |
1021 | + # # Replay correctly. |
1022 | + # self.switchToReplayMode() |
1023 | + # con1 = self.connect() |
1024 | + # con2 = self.connect() |
1025 | + # con1.close() |
1026 | + # con2.close() |
1027 | + |
1028 | + # # Replay in the wrong order. |
1029 | + # self.switchToReplayMode() |
1030 | + # con1 = self.connect() |
1031 | + # con2 = self.connect() |
1032 | + # self.assertRaises(RetryTest, con2.close) |
1033 | + |
1034 | + # @dont_retry |
1035 | + #def testConnectionParams(self): |
1036 | # Make sure we can correctly connect with different connection parms. |
1037 | - for mode in self.modes(): |
1038 | - for dbuser in ['launchpad', 'testadmin']: |
1039 | - connection_string = "%s user=%s" % ( |
1040 | - config.database.main_master, dbuser) |
1041 | - con = self.connect(connection_string) |
1042 | - cur = con.cursor() |
1043 | - cur.execute("SHOW session authorization") |
1044 | - self.failUnlessEqual(cur.fetchone()[0], dbuser) |
1045 | + # for mode in self.modes(): |
1046 | + # for dbuser in ['launchpad', 'testadmin']: |
1047 | + # connection_string = "%s user=%s" % ( |
1048 | + # config.database.main_master, dbuser) |
1049 | + # con = self.connect(connection_string) |
1050 | + # cur = con.cursor() |
1051 | + # cur.execute("SHOW session authorization") |
1052 | + # self.failUnlessEqual(cur.fetchone()[0], dbuser) |
1053 | |
1054 | # Confirm that unexpected connection parameters raises a RetryTest. |
1055 | - self.switchToReplayMode() |
1056 | - self.assertRaises(RetryTest, self.connect, "whoops") |
1057 | + # self.switchToReplayMode() |
1058 | + # self.assertRaises(RetryTest, self.connect, "whoops") |
1059 | |
1060 | - @dont_retry |
1061 | + # @dont_retry |
1062 | def testFailedConnection(self): |
1063 | # Ensure failed database connections are reproducable. |
1064 | for mode in self.modes(): |
1065 | @@ -168,13 +168,13 @@ |
1066 | psycopg2.OperationalError, self.connect, connection_string |
1067 | ) |
1068 | |
1069 | - @dont_retry |
1070 | + # @dont_retry |
1071 | def testNoopSession(self): |
1072 | # Minimal do-nothing case. |
1073 | for mode in self.modes(): |
1074 | con = self.connect() |
1075 | |
1076 | - @dont_retry |
1077 | + # @dont_retry |
1078 | def testSimpleQuery(self): |
1079 | # Ensure that we can script and replay a simple query. |
1080 | for mode in self.modes(): |
1081 | @@ -199,7 +199,7 @@ |
1082 | name = cur.fetchone()[0] |
1083 | self.assertEqual(name, 'carlos') |
1084 | |
1085 | - @dont_retry |
1086 | + # @dont_retry |
1087 | def testExceptions(self): |
1088 | # Confirm that expected exceptions are raised correctly. |
1089 | for mode in self.modes(): |
1090 | @@ -210,38 +210,38 @@ |
1091 | cur.execute, "SELECT blood FROM Stone" |
1092 | ) |
1093 | |
1094 | - @dont_retry |
1095 | - def testUnexpectedQuery(self): |
1096 | - for mode in self.modes(): |
1097 | - con = self.connect() |
1098 | - cur = con.cursor() |
1099 | - if mode != 'replay': |
1100 | - cur.execute("SELECT name FROM Person WHERE name='sabdfl'") |
1101 | - else: |
1102 | + # @dont_retry |
1103 | + #def testUnexpectedQuery(self): |
1104 | + # for mode in self.modes(): |
1105 | + # con = self.connect() |
1106 | + # cur = con.cursor() |
1107 | + # if mode != 'replay': |
1108 | + # cur.execute("SELECT name FROM Person WHERE name='sabdfl'") |
1109 | + # else: |
1110 | # Issue an unexpected query in replay mode. A RetryTest |
1111 | # exception should be raised. |
1112 | - self.assertRaises( |
1113 | - RetryTest, cur.execute, |
1114 | - "SELECT name FROM Person WHERE name='stub'" |
1115 | - ) |
1116 | + # self.assertRaises( |
1117 | + # RetryTest, cur.execute, |
1118 | + # "SELECT name FROM Person WHERE name='stub'" |
1119 | + # ) |
1120 | |
1121 | - @dont_retry |
1122 | - def testUnexpectedQueryParameters(self): |
1123 | - for mode in self.modes(): |
1124 | - con = self.connect() |
1125 | - cur = con.cursor() |
1126 | - query = "SELECT name FROM Person WHERE name=%s" |
1127 | - if mode != 'replay': |
1128 | - cur.execute(query, ('sabdfl',)) |
1129 | - else: |
1130 | + # @dont_retry |
1131 | + #def testUnexpectedQueryParameters(self): |
1132 | + # for mode in self.modes(): |
1133 | + # con = self.connect() |
1134 | + # cur = con.cursor() |
1135 | + # query = "SELECT name FROM Person WHERE name=%s" |
1136 | + # if mode != 'replay': |
1137 | + # cur.execute(query, ('sabdfl',)) |
1138 | + # else: |
1139 | # Issue a query with unexpected bound parameters in replay |
1140 | # mode. A RetryTest should be raised. |
1141 | - self.assertRaises( |
1142 | - RetryTest, cur.execute, |
1143 | - query, ('stub',) |
1144 | - ) |
1145 | + # self.assertRaises( |
1146 | + # RetryTest, cur.execute, |
1147 | + # query, ('stub',) |
1148 | + # ) |
1149 | |
1150 | - @dont_retry |
1151 | + # @dont_retry |
1152 | def testCommit(self): |
1153 | # Confirm commit behavior. |
1154 | for mode in self.modes(): |
1155 | @@ -283,7 +283,7 @@ |
1156 | """) |
1157 | con.commit() |
1158 | |
1159 | - @dont_retry |
1160 | + # @dont_retry |
1161 | def testRollback(self): |
1162 | # Confirm rollback behavior. |
1163 | for mode in self.modes(): |
1164 | @@ -323,7 +323,7 @@ |
1165 | "Rollback did not roll back changes." |
1166 | ) |
1167 | |
1168 | - @dont_retry |
1169 | + # @dont_retry |
1170 | def testFailedCommit(self): |
1171 | # Confirm exeptions raised on commit are recorded and replayed. |
1172 | for mode in self.modes(): |
1173 | @@ -344,7 +344,7 @@ |
1174 | else: |
1175 | self.assertRaises(psycopg2.InterfaceError, con.rollback) |
1176 | |
1177 | - @dont_retry |
1178 | + # @dont_retry |
1179 | def testFailedSetIsolationLevel(self): |
1180 | # Confirm exeptions raised on commit are recorded and replayed. |
1181 | for mode in self.modes(): |
1182 | @@ -354,7 +354,7 @@ |
1183 | psycopg2.InterfaceError, con.set_isolation_level, 666 |
1184 | ) |
1185 | |
1186 | - @dont_retry |
1187 | + # @dont_retry |
1188 | def testClose(self): |
1189 | # Confirm and record close behavior. |
1190 | for mode in self.modes(): |
1191 | @@ -376,7 +376,7 @@ |
1192 | self.fail( |
1193 | "Connection.close() now DB-API compliant. Fix test.") |
1194 | |
1195 | - @dont_retry |
1196 | + # @dont_retry |
1197 | def testCursorDescription(self): |
1198 | # Confirm cursor.description behavior. |
1199 | for mode in self.modes(): |
1200 | @@ -402,7 +402,7 @@ |
1201 | else: |
1202 | self.failUnlessEqual(direct_description, cur.description) |
1203 | |
1204 | - @dont_retry |
1205 | + # @dont_retry |
1206 | def testCursorRowcount(self): |
1207 | # Confirm and record cursor.rowcount behavior. |
1208 | for mode in self.modes(): |
1209 | @@ -443,7 +443,7 @@ |
1210 | cur.execute("DELETE FROM WikiName WHERE person=1") |
1211 | self.failUnlessEqual(cur.rowcount, 1) |
1212 | |
1213 | - @dont_retry |
1214 | + # @dont_retry |
1215 | def testCursorClose(self): |
1216 | # Confirm and record cursor.close behavior. |
1217 | for mode in self.modes(): |
1218 | @@ -457,7 +457,7 @@ |
1219 | cur = con.cursor() |
1220 | cur.execute("SELECT name FROM Person WHERE name='stub'") |
1221 | |
1222 | - @dont_retry |
1223 | + # @dont_retry |
1224 | def testFetchOne(self): |
1225 | for mode in self.modes(): |
1226 | con = self.connect() |
1227 | @@ -491,7 +491,7 @@ |
1228 | self.failUnlessEqual(row[0], i, "Bad result %s" % repr(row)) |
1229 | self.failUnless(cur.fetchone() is None, "Too many results") |
1230 | |
1231 | - @dont_retry |
1232 | + # @dont_retry |
1233 | def testCursorIteration(self): |
1234 | # psycopg1 does not support this extension. |
1235 | for mode in self.modes(): |
1236 | @@ -516,7 +516,7 @@ |
1237 | ## ) |
1238 | ## self.failUnlessEqual(row[0], 1, "Bad result %s" % repr(row)) |
1239 | |
1240 | - @dont_retry |
1241 | + # @dont_retry |
1242 | def testFetchAll(self): |
1243 | for mode in self.modes(): |
1244 | con = self.connect() |
1245 | |
1246 | === modified file 'lib/canonical/testing/mockdb.py' |
1247 | --- lib/canonical/testing/mockdb.py 2009-06-25 05:30:52 +0000 |
1248 | +++ lib/canonical/testing/mockdb.py 2009-08-05 18:52:52 +0000 |
1249 | @@ -25,7 +25,7 @@ |
1250 | import urllib |
1251 | |
1252 | import psycopg2 |
1253 | -from zope.testing.testrunner import RetryTest |
1254 | +# from zope.testing.testrunner import RetryTest |
1255 | |
1256 | from canonical.config import config |
1257 | |
1258 | @@ -386,7 +386,8 @@ |
1259 | if os.path.exists(self.script_filename): |
1260 | os.unlink(self.script_filename) |
1261 | self.invalid = True |
1262 | - raise RetryTest(reason) |
1263 | + raise RetryTest(reason) # Leaving this as a name error: this should |
1264 | + # not be called unless we reinstate the retry behavior in zope.testing. |
1265 | |
1266 | |
1267 | class MockDbConnection: |
1268 | |
1269 | === modified file 'lib/canonical/testing/tests/test_mockdb.py' |
1270 | --- lib/canonical/testing/tests/test_mockdb.py 2009-06-25 05:30:52 +0000 |
1271 | +++ lib/canonical/testing/tests/test_mockdb.py 2009-08-05 18:52:52 +0000 |
1272 | @@ -11,7 +11,7 @@ |
1273 | import unittest |
1274 | |
1275 | from zope.testing.doctestunit import DocTestSuite |
1276 | -from zope.testing.testrunner import dont_retry, RetryTest |
1277 | +#from zope.testing.testrunner import dont_retry, RetryTest |
1278 | |
1279 | from canonical.testing import mockdb |
1280 | |
1281 | @@ -24,7 +24,7 @@ |
1282 | if os.path.exists(self.script_filename): |
1283 | os.unlink(self.script_filename) |
1284 | |
1285 | - @dont_retry |
1286 | + #@dont_retry |
1287 | def testSerialize(self): |
1288 | # Ensure the scripts can store and retrieve their logs |
1289 | recorder = mockdb.ScriptRecorder(self.script_filename) |
1290 | @@ -34,29 +34,29 @@ |
1291 | replayer = mockdb.ScriptPlayer(self.script_filename) |
1292 | self.failUnlessEqual(replayer.log, ['Arbitrary Data']) |
1293 | |
1294 | - @dont_retry |
1295 | - def testHandleInvalidScript(self): |
1296 | + #@dont_retry |
1297 | + #def testHandleInvalidScript(self): |
1298 | # Ensure a RetryTest exception is raised and the invalid script |
1299 | # file removed when handleInvalidScript() is called |
1300 | - recorder = mockdb.ScriptRecorder(self.script_filename) |
1301 | - recorder.store() |
1302 | - |
1303 | - replayer = mockdb.ScriptPlayer(self.script_filename) |
1304 | - |
1305 | - self.assertRaises( |
1306 | - RetryTest, replayer.handleInvalidScript, 'Reason') |
1307 | - self.failIf(os.path.exists(self.script_filename)) |
1308 | - |
1309 | - @dont_retry |
1310 | - def testShortScript(self): |
1311 | + # recorder = mockdb.ScriptRecorder(self.script_filename) |
1312 | + # recorder.store() |
1313 | + |
1314 | + # replayer = mockdb.ScriptPlayer(self.script_filename) |
1315 | + |
1316 | + # self.assertRaises( |
1317 | + # RetryTest, replayer.handleInvalidScript, 'Reason') |
1318 | + # self.failIf(os.path.exists(self.script_filename)) |
1319 | + |
1320 | + #@dont_retry |
1321 | + #def testShortScript(self): |
1322 | # Ensure a RetryTest exception is raised if an attempt is made |
1323 | # to pull results from an exhausted script. |
1324 | - recorder = mockdb.ScriptRecorder(self.script_filename) |
1325 | - recorder.store() |
1326 | - replayer = mockdb.ScriptPlayer(self.script_filename) |
1327 | - self.assertRaises(RetryTest, replayer.getNextEntry, None, None) |
1328 | + # recorder = mockdb.ScriptRecorder(self.script_filename) |
1329 | + # recorder.store() |
1330 | + # replayer = mockdb.ScriptPlayer(self.script_filename) |
1331 | + # self.assertRaises(RetryTest, replayer.getNextEntry, None, None) |
1332 | |
1333 | - @dont_retry |
1334 | + #@dont_retry |
1335 | def testScriptFilename(self): |
1336 | # Ensure evil characters in the key don't mess up the script_filename |
1337 | # results. Only '/' is really evil - other chars should all work |
1338 | @@ -86,7 +86,7 @@ |
1339 | # This test does not use @dont_retry. |
1340 | # It needs to leak RetryTest exeptions as it tests that the |
1341 | # test runner is handling them correctly. |
1342 | - def testRetryTestRetriesTest(self): |
1343 | + #def testRetryTestRetriesTest(self): |
1344 | # The first time this test is run it raises a RetryTest exception. |
1345 | # The second time it is run it succeeds. This means that this |
1346 | # test will fail if RetryTest handling is not being done correctly |
1347 | @@ -97,106 +97,106 @@ |
1348 | # version of zope.testing is in use and to minimize the zope.testing |
1349 | # patch until we decide if RetryTest handling is to be pushed |
1350 | # upstream or not. |
1351 | - MockDbTestCase._retry_count += 1 |
1352 | - if MockDbTestCase._retry_count % 2 == 1: |
1353 | - raise RetryTest( |
1354 | - "Testing RetryTest behavior. This exception will be raised " |
1355 | - "but the test runner doesn't consider it a failure") |
1356 | + # MockDbTestCase._retry_count += 1 |
1357 | + # if MockDbTestCase._retry_count % 2 == 1: |
1358 | + # raise RetryTest( |
1359 | + # "Testing RetryTest behavior. This exception will be raised " |
1360 | + # "but the test runner doesn't consider it a failure") |
1361 | |
1362 | |
1363 | _doctest_retry_count = 0 |
1364 | |
1365 | -def retry_on_odd_numbered_calls(): |
1366 | - """Helper for doctest RetryTest test. |
1367 | +#def retry_on_odd_numbered_calls(): |
1368 | +# """Helper for doctest RetryTest test. |
1369 | |
1370 | - This helper raises a RetryTest exception on odd numbered calls, |
1371 | - and prints 'Retry not raised' on even numbered calls. |
1372 | +# This helper raises a RetryTest exception on odd numbered calls, |
1373 | +# and prints 'Retry not raised' on even numbered calls. |
1374 | |
1375 | - >>> try: |
1376 | - ... retry_on_odd_numbered_calls() |
1377 | - ... except RetryTest: |
1378 | - ... print "Caught RetryTest." |
1379 | - ... |
1380 | - Retry raised. |
1381 | - Caught RetryTest. |
1382 | - >>> try: |
1383 | - ... retry_on_odd_numbered_calls() |
1384 | - ... except RetryTest: |
1385 | - ... print "Caught RetryTest." |
1386 | - ... |
1387 | - Retry not raised. |
1388 | - """ |
1389 | - global _doctest_retry_count |
1390 | - _doctest_retry_count += 1 |
1391 | - if _doctest_retry_count % 2 == 1: |
1392 | - print "Retry raised." |
1393 | - raise RetryTest |
1394 | - print "Retry not raised." |
1395 | - |
1396 | - |
1397 | -def testRetryTestInDoctest_will_raise_but_testrunner_ignores_it(): |
1398 | - """Test a RetryTest exception in a doctest works as expected. |
1399 | - |
1400 | - This doctest raises a RetryTest exception the first time it is run. |
1401 | - On the second run, it succeeds. |
1402 | - |
1403 | - If the testrunner is correctly handling RetryTest exceptions raised |
1404 | - by doctests, then the RetryTest exception will not be reported as |
1405 | - a failure. This test will then be rerun and succeed. |
1406 | - |
1407 | - If the testrunner is not correctly handling RetryTest exceptions, |
1408 | - then the RetryTesst exception will be flagged as an error. |
1409 | - |
1410 | - This test confirms that a RetryException raised where no exception |
1411 | - was expected works. |
1412 | - |
1413 | - >>> retry_on_odd_numbered_calls() |
1414 | - Retry not raised. |
1415 | - """ |
1416 | - |
1417 | - |
1418 | -def retry_on_odd_numbered_calls2(): |
1419 | - """Helper for doctest RetryTest test. |
1420 | - |
1421 | - This helper raises a RetryTest exception on odd numbered calls, |
1422 | - and a RuntimeError on even numbered calls. |
1423 | - |
1424 | - >>> try: |
1425 | - ... retry_on_odd_numbered_calls2() |
1426 | - ... except RetryTest: |
1427 | - ... print "Caught RetryTest." |
1428 | - ... |
1429 | - Retry raised. |
1430 | - Caught RetryTest. |
1431 | - >>> try: |
1432 | - ... retry_on_odd_numbered_calls2() |
1433 | - ... except RetryTest: |
1434 | - ... print "Caught RetryTest." |
1435 | - ... |
1436 | - Traceback (most recent call last): |
1437 | - ... |
1438 | - RuntimeError: Retry not raised. |
1439 | - """ |
1440 | - global _doctest_retry_count |
1441 | - _doctest_retry_count += 1 |
1442 | - if _doctest_retry_count % 2 == 1: |
1443 | - print "Retry raised." |
1444 | - raise RetryTest |
1445 | - raise RuntimeError("Retry not raised.") |
1446 | - |
1447 | - |
1448 | -def testRetryTestInDoctest2(): |
1449 | - """Test a RetryTest exception in a doctest works as expected. |
1450 | - |
1451 | - This test is the same as testRetryTestInDoctest, except it confirms |
1452 | - that a RetryException raised where a different exception was expected |
1453 | - works. |
1454 | - |
1455 | - >>> retry_on_odd_numbered_calls2() |
1456 | - Traceback (most recent call last): |
1457 | - ... |
1458 | - RuntimeError: Retry not raised. |
1459 | - """ |
1460 | +# >>> try: |
1461 | +# ... retry_on_odd_numbered_calls() |
1462 | +# ... except RetryTest: |
1463 | +# ... print "Caught RetryTest." |
1464 | +# ... |
1465 | +# Retry raised. |
1466 | +# Caught RetryTest. |
1467 | +# >>> try: |
1468 | +# ... retry_on_odd_numbered_calls() |
1469 | +# ... except RetryTest: |
1470 | +# ... print "Caught RetryTest." |
1471 | +# ... |
1472 | +# Retry not raised. |
1473 | +# """ |
1474 | +# global _doctest_retry_count |
1475 | +# _doctest_retry_count += 1 |
1476 | +# if _doctest_retry_count % 2 == 1: |
1477 | +# print "Retry raised." |
1478 | +# raise RetryTest |
1479 | +# print "Retry not raised." |
1480 | + |
1481 | + |
1482 | +#def testRetryTestInDoctest_will_raise_but_testrunner_ignores_it(): |
1483 | +# """Test a RetryTest exception in a doctest works as expected. |
1484 | + |
1485 | +# This doctest raises a RetryTest exception the first time it is run. |
1486 | +# On the second run, it succeeds. |
1487 | + |
1488 | +# If the testrunner is correctly handling RetryTest exceptions raised |
1489 | +# by doctests, then the RetryTest exception will not be reported as |
1490 | +# a failure. This test will then be rerun and succeed. |
1491 | + |
1492 | +# If the testrunner is not correctly handling RetryTest exceptions, |
1493 | +# then the RetryTesst exception will be flagged as an error. |
1494 | + |
1495 | +# This test confirms that a RetryException raised where no exception |
1496 | +# was expected works. |
1497 | + |
1498 | +# >>> retry_on_odd_numbered_calls() |
1499 | +# Retry not raised. |
1500 | +# """ |
1501 | + |
1502 | + |
1503 | +#def retry_on_odd_numbered_calls2(): |
1504 | +# """Helper for doctest RetryTest test. |
1505 | + |
1506 | +# This helper raises a RetryTest exception on odd numbered calls, |
1507 | +# and a RuntimeError on even numbered calls. |
1508 | + |
1509 | +# >>> try: |
1510 | +# ... retry_on_odd_numbered_calls2() |
1511 | +# ... except RetryTest: |
1512 | +# ... print "Caught RetryTest." |
1513 | +# ... |
1514 | +# Retry raised. |
1515 | +# Caught RetryTest. |
1516 | +# >>> try: |
1517 | +# ... retry_on_odd_numbered_calls2() |
1518 | +# ... except RetryTest: |
1519 | +# ... print "Caught RetryTest." |
1520 | +# ... |
1521 | +# Traceback (most recent call last): |
1522 | +# ... |
1523 | +# RuntimeError: Retry not raised. |
1524 | +# """ |
1525 | +# global _doctest_retry_count |
1526 | +# _doctest_retry_count += 1 |
1527 | +# if _doctest_retry_count % 2 == 1: |
1528 | +# print "Retry raised." |
1529 | +# raise RetryTest |
1530 | +# raise RuntimeError("Retry not raised.") |
1531 | + |
1532 | + |
1533 | +#def testRetryTestInDoctest2(): |
1534 | +# """Test a RetryTest exception in a doctest works as expected. |
1535 | + |
1536 | +# This test is the same as testRetryTestInDoctest, except it confirms |
1537 | +# that a RetryException raised where a different exception was expected |
1538 | +# works. |
1539 | + |
1540 | +# >>> retry_on_odd_numbered_calls2() |
1541 | +# Traceback (most recent call last): |
1542 | +# ... |
1543 | +# RuntimeError: Retry not raised. |
1544 | +# """ |
1545 | |
1546 | |
1547 | |
1548 | |
1549 | === modified file 'lib/canonical/widgets/date.py' |
1550 | --- lib/canonical/widgets/date.py 2009-06-25 05:30:52 +0000 |
1551 | +++ lib/canonical/widgets/date.py 2009-08-13 19:36:01 +0000 |
1552 | @@ -80,7 +80,7 @@ |
1553 | >>> print widget.getInputValue() #doctest: +ELLIPSIS |
1554 | Traceback (most recent call last): |
1555 | ... |
1556 | - WidgetInputError: (... Please pick a date after 2006-05-22 17:00:00) |
1557 | + WidgetInputError: (...Please pick a date after 2006-05-22 17:00:00...) |
1558 | |
1559 | If the date provided is greater than from_date then the widget works as |
1560 | expected. |
1561 | @@ -96,7 +96,7 @@ |
1562 | >>> print widget.getInputValue() #doctest: +ELLIPSIS |
1563 | Traceback (most recent call last): |
1564 | ... |
1565 | - WidgetInputError: (... Please pick a date before 2008-01-25 16:00:00) |
1566 | + WidgetInputError: (...Please pick a date before 2008-01-25 16:00:00...) |
1567 | |
1568 | A datetime picker can be disabled initially: |
1569 | |
1570 | @@ -288,7 +288,7 @@ |
1571 | value = super(DateTimeWidget, self).getInputValue() |
1572 | if value is None: |
1573 | return None |
1574 | - # Establish if the value is within the date range. |
1575 | + # Establish if the value is within the date range. |
1576 | self._align_date_constraints_with_time_zone() |
1577 | if self.from_date is not None and value < self.from_date: |
1578 | limit = self.from_date.strftime(self.timeformat) |
1579 | @@ -570,4 +570,3 @@ |
1580 | return u"" |
1581 | value = value.astimezone(time_zone) |
1582 | return escape(value.strftime("%Y-%m-%d %H:%M:%S %Z")) |
1583 | - |
1584 | |
1585 | === modified file 'lib/lp/answers/interfaces/questiontarget.py' |
1586 | --- lib/lp/answers/interfaces/questiontarget.py 2009-06-24 23:10:46 +0000 |
1587 | +++ lib/lp/answers/interfaces/questiontarget.py 2009-08-13 15:22:00 +0000 |
1588 | @@ -13,8 +13,6 @@ |
1589 | 'ISearchQuestionsForm', |
1590 | ] |
1591 | |
1592 | -import sets |
1593 | - |
1594 | from zope.interface import Interface |
1595 | from zope.schema import Choice, List, Set, TextLine |
1596 | |
1597 | @@ -156,7 +154,7 @@ |
1598 | |
1599 | status = Set(title=_('Status'), required=False, |
1600 | value_type=Choice(vocabulary=QuestionStatus), |
1601 | - default=sets.Set(QUESTION_STATUS_DEFAULT_SEARCH)) |
1602 | + default=set(QUESTION_STATUS_DEFAULT_SEARCH)) |
1603 | |
1604 | |
1605 | class IAnswersFrontPageSearchForm(ISearchQuestionsForm): |
1606 | |
1607 | === modified file 'lib/lp/answers/stories/answer-contact-report.txt' |
1608 | --- lib/lp/answers/stories/answer-contact-report.txt 2009-06-12 16:36:02 +0000 |
1609 | +++ lib/lp/answers/stories/answer-contact-report.txt 2009-08-13 13:33:26 +0000 |
1610 | @@ -1,6 +1,6 @@ |
1611 | = Answer Contact Report = |
1612 | |
1613 | -To view the answer contact report for a given person, the user chooses |
1614 | +To view the answer contact report for a given person, the user chooses |
1615 | the 'Answer Contact For' link from the actions portlet while viewing |
1616 | the Person's page. |
1617 | |
1618 | @@ -11,7 +11,7 @@ |
1619 | |
1620 | Since No Privileges Person is not an answer contact, the report states |
1621 | that. |
1622 | - |
1623 | + |
1624 | >>> content = find_main_content(anon_browser.contents) |
1625 | >>> print content.find('p').renderContents() |
1626 | No Privileges Person is not an answer contact for any project. |
1627 | @@ -23,7 +23,7 @@ |
1628 | >>> anon_browser.getLink('Answer contact for').click() |
1629 | >>> print anon_browser.title |
1630 | Projects for which Foo Bar is an answer contact |
1631 | - |
1632 | + |
1633 | >>> content = find_tag_by_id( |
1634 | ... anon_browser.contents, "direct-answer-contacts-for-list") |
1635 | >>> print extract_text(content).encode('ascii', 'backslashreplace') |
1636 | @@ -35,7 +35,7 @@ |
1637 | >>> print extract_text(content) |
1638 | Gnome Baker |
1639 | The Gnome Panel Applets |
1640 | - |
1641 | + |
1642 | Clicking on the name of the project will show the project answers. |
1643 | |
1644 | >>> anon_browser.getLink('Gnome Baker').click() |
1645 | @@ -51,18 +51,18 @@ |
1646 | >>> browser.getLink('Answer contact for').click() |
1647 | >>> print browser.title |
1648 | Projects for which Sample Person is an answer contact |
1649 | - |
1650 | + |
1651 | >>> content = find_tag_by_id( |
1652 | ... browser.contents, "team-answer-contacts-for-list") |
1653 | >>> print extract_text(content) |
1654 | Gnome Baker — Remove team |
1655 | The Gnome Panel Applets — Remove team |
1656 | - |
1657 | + |
1658 | >>> browser.getLink(id="gnomebaker-setteamanswercontact").click() |
1659 | >>> print browser.title |
1660 | Answer contact for Gnome Baker |
1661 | - |
1662 | -The Remove yourself/team links only appears in his profile. He cannot |
1663 | + |
1664 | +The Remove yourself/team links only appears in his profile. He cannot |
1665 | see the link for other users |
1666 | |
1667 | >>> browser.open( |
1668 | @@ -70,7 +70,7 @@ |
1669 | >>> browser.getLink('Answer contact for').click() |
1670 | >>> print browser.title |
1671 | Projects for which Foo Bar is an answer contact |
1672 | - |
1673 | + |
1674 | >>> content = find_tag_by_id(browser.contents, "direct-answer-contacts-for-list") |
1675 | >>> print extract_text(content).encode('ascii', 'backslashreplace') |
1676 | Gnome Baker |
1677 | |
1678 | === modified file 'lib/lp/answers/stories/questions-index.txt' |
1679 | --- lib/lp/answers/stories/questions-index.txt 2009-03-24 12:43:49 +0000 |
1680 | +++ lib/lp/answers/stories/questions-index.txt 2009-08-13 21:32:59 +0000 |
1681 | @@ -60,7 +60,7 @@ |
1682 | ... anon_browser.contents, 'most-active-projects')) |
1683 | Most active projects |
1684 | Ubuntu |
1685 | - Mozilla Firefox |
1686 | + Mozilla Firefox ... |
1687 | |
1688 | Clicking on these project links will bring the user to the project |
1689 | Answers front page: |
1690 | |
1691 | === modified file 'lib/lp/answers/templates/person-answer-contact-for.pt' |
1692 | --- lib/lp/answers/templates/person-answer-contact-for.pt 2009-07-17 17:59:07 +0000 |
1693 | +++ lib/lp/answers/templates/person-answer-contact-for.pt 2009-08-13 13:33:26 +0000 |
1694 | @@ -23,8 +23,8 @@ |
1695 | |
1696 | <ul class="listing" id="direct-answer-contacts-for-list"> |
1697 | <li tal:repeat="question_target view/direct_question_targets"> |
1698 | - <a href="#" |
1699 | - tal:attributes="href string:${question_target/fmt:url}" |
1700 | + <a |
1701 | + tal:attributes="href question_target/fmt:url:answers" |
1702 | tal:content="question_target/title">Project Title</a> |
1703 | <tal:link condition="view/showRemoveYourselfLink"> |
1704 | — |
1705 | @@ -42,8 +42,8 @@ |
1706 | |
1707 | <ul class="listing" id="team-answer-contacts-for-list"> |
1708 | <li tal:repeat="question_target view/team_question_targets"> |
1709 | - <a href="#" |
1710 | - tal:attributes="href string:${question_target/fmt:url}" |
1711 | + <a |
1712 | + tal:attributes="href question_target/fmt:url:answers" |
1713 | tal:content="question_target/title">Project Title</a> |
1714 | <tal:link condition="view/showRemoveYourselfLink"> |
1715 | — |
1716 | |
1717 | === modified file 'lib/lp/answers/templates/questions-index.pt' |
1718 | --- lib/lp/answers/templates/questions-index.pt 2009-07-17 17:59:07 +0000 |
1719 | +++ lib/lp/answers/templates/questions-index.pt 2009-08-13 21:32:59 +0000 |
1720 | @@ -81,11 +81,7 @@ |
1721 | tal:condition="projects" |
1722 | style="list-style: none;"> |
1723 | <li tal:repeat="project projects"> |
1724 | - <a href="#" |
1725 | - tal:attributes="href project/fmt:url"> |
1726 | - <img alt="" tal:replace="structure project/image:icon" /> |
1727 | - <span tal:replace="project/displayname" /> |
1728 | - </a> |
1729 | + <a tal:replace="structure project/fmt:link:answers"/> |
1730 | </li> |
1731 | </ul> |
1732 | </div> |
1733 | @@ -110,28 +106,29 @@ |
1734 | </table> |
1735 | </div> |
1736 | </div> |
1737 | - <div id="application-footer"> |
1738 | - <div> |
1739 | - <strong |
1740 | - tal:content="view/answered_question_count" |
1741 | - >52</strong> |
1742 | - questions answered and |
1743 | - <strong |
1744 | - tal:content="view/solved_question_count" |
1745 | - >52</strong> |
1746 | - questions solved out of |
1747 | - </div> |
1748 | - <div> |
1749 | - <strong |
1750 | - tal:content="view/question_count" |
1751 | - >318</strong> |
1752 | - questions asked across |
1753 | - <strong |
1754 | - tal:content="view/projects_with_questions_count" |
1755 | - >28</strong> |
1756 | - projects |
1757 | - </div> |
1758 | - </div> |
1759 | + |
1760 | + <div id="application-footer"> |
1761 | + <div> |
1762 | + <strong |
1763 | + tal:content="view/answered_question_count" |
1764 | + >52</strong> |
1765 | + questions answered and |
1766 | + <strong |
1767 | + tal:content="view/solved_question_count" |
1768 | + >52</strong> |
1769 | + questions solved out of |
1770 | + </div> |
1771 | + <div> |
1772 | + <strong |
1773 | + tal:content="view/question_count" |
1774 | + >318</strong> |
1775 | + questions asked across |
1776 | + <strong |
1777 | + tal:content="view/projects_with_questions_count" |
1778 | + >28</strong> |
1779 | + projects |
1780 | + </div> |
1781 | + </div> |
1782 | |
1783 | </div><!--main--> |
1784 | |
1785 | |
1786 | === modified file 'lib/lp/app/browser/tests/base-layout.txt' |
1787 | --- lib/lp/app/browser/tests/base-layout.txt 2009-08-06 11:07:45 +0000 |
1788 | +++ lib/lp/app/browser/tests/base-layout.txt 2009-08-13 02:24:56 +0000 |
1789 | @@ -44,7 +44,6 @@ |
1790 | <body id="document" class="tab-overview main_side public yui-skin-sam"> |
1791 | <div class="yui-d0"> |
1792 | <div id="locationbar"> ... |
1793 | - <form id="globalsearch" ... |
1794 | <div id="lp-hierarchy" class="home">... |
1795 | <div class="location-portlet top-portlet"> |
1796 | <img ... |
1797 | @@ -77,7 +76,8 @@ |
1798 | </div><!-- yui-b side --> |
1799 | </div><!-- yui-t4 --> |
1800 | <div id="footer" class="footer"> ... |
1801 | - </div><!-- footer--> |
1802 | + <form id="globalsearch" ... |
1803 | + </div> |
1804 | </div><!-- yui-d0--> |
1805 | <script>LP.client.cache['context'] ... |
1806 | </body> |
1807 | @@ -105,7 +105,6 @@ |
1808 | <body id="document" class="tab-overview main_only public yui-skin-sam"> |
1809 | <div class="yui-d0"> |
1810 | <div id="locationbar"> ... |
1811 | - <form id="globalsearch" ... |
1812 | <div id="lp-hierarchy" class="home">... |
1813 | <div class="location-portlet top-portlet"> |
1814 | <img ... |
1815 | @@ -134,7 +133,8 @@ |
1816 | <!-- yui-b side --> |
1817 | <!-- yui-t4 --> |
1818 | <div id="footer" class="footer"> ... |
1819 | - </div><!-- footer--> |
1820 | + <form id="globalsearch" ... |
1821 | + </div> |
1822 | </div><!-- yui-d0--> |
1823 | <script>LP.client.cache['context'] ... |
1824 | </body> |
1825 | @@ -191,7 +191,7 @@ |
1826 | <!-- yui-b side --> |
1827 | <!-- yui-t4 --> |
1828 | <div id="footer" class="footer"> ... |
1829 | - </div><!-- footer--> |
1830 | + </div> |
1831 | </div><!-- yui-d0--> |
1832 | <script>LP.client.cache['context'] ... |
1833 | </body> |
1834 | @@ -241,7 +241,7 @@ |
1835 | <!-- yui-b side --> |
1836 | <!-- yui-t4 --> |
1837 | <div id="footer" class="footer"> ... |
1838 | - </div><!-- footer--> |
1839 | + </div> |
1840 | </div><!-- yui-d0--> |
1841 | <script>LP.client.cache['context'] ... |
1842 | </body> |
1843 | |
1844 | === modified file 'lib/lp/app/templates/base-layout-macros.pt' |
1845 | --- lib/lp/app/templates/base-layout-macros.pt 2009-08-06 11:07:45 +0000 |
1846 | +++ lib/lp/app/templates/base-layout-macros.pt 2009-08-13 02:24:56 +0000 |
1847 | @@ -330,4 +330,41 @@ |
1848 | </ul> |
1849 | </metal:location-tabs> |
1850 | |
1851 | + |
1852 | +<metal:footer define-macro="footer"> |
1853 | + <div id="footer" class="footer"> |
1854 | + <div class="lp-arcana"> |
1855 | + <img src="/@@/launchpad-logo-and-name-hierarchy.png" alt="Launchpad"/> |
1856 | + • |
1857 | + <a href="/+tour">Take the tour</a> |
1858 | + • |
1859 | + <a href="https://help.launchpad.net/">Read the guide</a> |
1860 | + |
1861 | + <form id="globalsearch" method="get" accept-charset="UTF-8" |
1862 | + class="sprite-after search-icon" |
1863 | + tal:condition="view/macro:pagehas/globalsearch" |
1864 | + tal:attributes="action string:${rooturl}+search"> |
1865 | + <input type="search" id="search-text" name="field.text" /> |
1866 | + </form> |
1867 | + </div> |
1868 | + |
1869 | + <div class="colophon"> |
1870 | + © 2004-2009 |
1871 | + <a href="http://canonical.com/">Canonical Ltd.</a> |
1872 | + • |
1873 | + <a href="/legal">Terms of use</a> |
1874 | + • |
1875 | + <a href="/feedback" |
1876 | + tal:condition="request/lp:person">Contact us</a> |
1877 | + <span id="lp-version" tal:condition="not:is_lpnet"> |
1878 | + • |
1879 | + <a href="https://help.launchpad.net/LaunchpadReleases" |
1880 | + tal:content="version"/> |
1881 | + <tal:devmode condition="devmode">devmode</tal:devmode> |
1882 | + <tal:demo condition="is_demo">demo site</tal:demo> |
1883 | + <tal:edge condition="is_edge">beta site</tal:edge> |
1884 | + </span> |
1885 | + </div> |
1886 | + </div> |
1887 | +</metal:footer> |
1888 | </macros> |
1889 | |
1890 | === modified file 'lib/lp/app/templates/base-layout.pt' |
1891 | --- lib/lp/app/templates/base-layout.pt 2009-08-11 04:35:26 +0000 |
1892 | +++ lib/lp/app/templates/base-layout.pt 2009-08-13 02:24:56 +0000 |
1893 | @@ -81,12 +81,6 @@ |
1894 | <div class="yui-d0"> |
1895 | <div id="locationbar"> |
1896 | <tal:login replace="structure context/@@login_status" /> |
1897 | - <form id="globalsearch" method="get" accept-charset="UTF-8" |
1898 | - class="sprite search-icon" |
1899 | - tal:condition="view/macro:pagehas/globalsearch" |
1900 | - tal:attributes="action string:${rooturl}+search"> |
1901 | - <input type="search" id="search-text" name="field.text" /> |
1902 | - </form> |
1903 | <tal:hierarchy replace="structure context/@@+hierarchy" /> |
1904 | </div><!--id="locationbar"--> |
1905 | |
1906 | @@ -135,28 +129,8 @@ |
1907 | </div><!-- yui-b side --> |
1908 | </div><!-- yui-t4 --> |
1909 | |
1910 | - <div id="footer" class="footer"> |
1911 | - <div id="lp-arcana"> |
1912 | - © 2004-2009 <a |
1913 | - href="http://canonical.com/">Canonical Ltd.</a> | |
1914 | - <a href="/legal">Terms of use</a> |
1915 | - <span id="lp-version" tal:condition="not:is_lpnet"> | |
1916 | - <a href="https://help.launchpad.net/LaunchpadReleases" |
1917 | - tal:content="version"/> |
1918 | - <tal:devmode condition="devmode">devmode</tal:devmode> |
1919 | - <tal:demo condition="is_demo">demo site</tal:demo> |
1920 | - <tal:edge condition="is_edge">beta site</tal:edge> |
1921 | - </span> |
1922 | - </div> |
1923 | - |
1924 | - <div id="colophon"> |
1925 | - <a href="/+tour" |
1926 | - tal:condition="not:request/lp:person">What is Launchpad?</a> |
1927 | - <a href="/feedback" |
1928 | - tal:condition="request/lp:person">Contact us</a> | |
1929 | - <a href="https://help.launchpad.net/">Get help with Launchpad</a> |
1930 | - </div> |
1931 | - </div><!-- footer--> |
1932 | + <metal:footer |
1933 | + use-macro="context/@@+base-layout-macros/footer"/> |
1934 | </div><!-- yui-d0--> |
1935 | |
1936 | <metal:lp-client-cache |
1937 | |
1938 | === modified file 'lib/lp/bugs/stories/bugtracker/xx-bugtracker-handshake-tokens.txt' |
1939 | --- lib/lp/bugs/stories/bugtracker/xx-bugtracker-handshake-tokens.txt 2009-06-12 16:36:02 +0000 |
1940 | +++ lib/lp/bugs/stories/bugtracker/xx-bugtracker-handshake-tokens.txt 2009-07-16 13:28:25 +0000 |
1941 | @@ -24,4 +24,4 @@ |
1942 | >>> anon_browser.open(token_url) |
1943 | Traceback (most recent call last): |
1944 | ... |
1945 | - HTTPError: HTTP Error 405: Method Not Allowed |
1946 | + httperror_seek_wrapper: HTTP Error 405: Method Not Allowed |
1947 | |
1948 | === modified file 'lib/lp/bugs/stories/bugtracker/xx-bugtracker-remote-bug.txt' |
1949 | --- lib/lp/bugs/stories/bugtracker/xx-bugtracker-remote-bug.txt 2009-08-11 06:29:52 +0000 |
1950 | +++ lib/lp/bugs/stories/bugtracker/xx-bugtracker-remote-bug.txt 2009-08-12 13:34:48 +0000 |
1951 | @@ -38,7 +38,7 @@ |
1952 | >>> browser.open('http://launchpad.dev/bugs/bugtrackers/mozilla.org/99999') |
1953 | Traceback (most recent call last): |
1954 | ... |
1955 | - HTTPError: HTTP Error 404: Not Found |
1956 | + httperror_seek_wrapper: HTTP Error 404: Not Found |
1957 | >>> browser.handleErrors = False |
1958 | |
1959 | |
1960 | |
1961 | === modified file 'lib/lp/bugs/stories/bugwatches/xx-bugwatch-comments.txt' |
1962 | --- lib/lp/bugs/stories/bugwatches/xx-bugwatch-comments.txt 2009-07-01 13:16:44 +0000 |
1963 | +++ lib/lp/bugs/stories/bugwatches/xx-bugwatch-comments.txt 2009-08-13 21:32:59 +0000 |
1964 | @@ -83,7 +83,7 @@ |
1965 | Launchpad Beta Testers team such as sabdfl: |
1966 | |
1967 | >>> sabdfl_browser.open( |
1968 | - ... 'http://launchpad.dev/redfish/+bug/15/comments/1') |
1969 | + ... 'http://bugs.launchpad.dev/redfish/+bug/15/comments/1') |
1970 | >>> print_comments(sabdfl_browser.contents) |
1971 | <p>Package: gnome-volume-<wbr></wbr>manager<br /> |
1972 | Version: 1.2.0-1<br /> |
1973 | @@ -125,11 +125,12 @@ |
1974 | >>> logout() |
1975 | |
1976 | >>> sabdfl_browser.open( |
1977 | - ... 'http://launchpad.dev/redfish/+bug/15/comments/1') |
1978 | + ... 'http://bugs.launchpad.dev/redfish/+bug/15/comments/1') |
1979 | >>> print_comments(sabdfl_browser.contents) |
1980 | |
1981 | Anonymous users can't see the comment either. |
1982 | |
1983 | - >>> anon_browser.open('http://launchpad.dev/redfish/+bug/15/comments/1') |
1984 | + >>> anon_browser.open( |
1985 | + ... 'http://bugs.launchpad.dev/redfish/+bug/15/comments/1') |
1986 | >>> print_comments(anon_browser.contents) |
1987 | |
1988 | |
1989 | === modified file 'lib/lp/code/stories/branches/xx-upload-directions.txt' |
1990 | --- lib/lp/code/stories/branches/xx-upload-directions.txt 2009-04-17 10:32:16 +0000 |
1991 | +++ lib/lp/code/stories/branches/xx-upload-directions.txt 2009-08-13 21:32:59 +0000 |
1992 | @@ -45,7 +45,7 @@ |
1993 | >>> instructions = find_tag_by_id(content, 'upload-directions') |
1994 | >>> print instructions.renderContents() |
1995 | Only |
1996 | - <a href="/~name12">Sample Person</a> |
1997 | + <a href="http://launchpad.dev/~name12">Sample Person</a> |
1998 | can upload to this branch. If you are Sample Person please |
1999 | <a href="+login">log in</a> for upload directions. |
2000 | |
2001 | @@ -57,7 +57,7 @@ |
2002 | >>> instructions = find_tag_by_id(content, 'upload-directions') |
2003 | >>> print instructions.renderContents() |
2004 | You cannot upload to this branch. Only |
2005 | - <a href="/~name12">Sample Person</a> |
2006 | + <a href="http://launchpad.dev/~name12">Sample Person</a> |
2007 | can upload to this branch. |
2008 | |
2009 | The user is the owner of the branch and logs in. The page gives the full upload |
2010 | @@ -90,7 +90,7 @@ |
2011 | >>> instructions = find_tag_by_id(content, 'ssh-key-directions') |
2012 | >>> print instructions.renderContents() |
2013 | To authenticate with the Launchpad branch upload service, you need to |
2014 | - <a href="/~name12/+editsshkeys"> |
2015 | + <a href="http://launchpad.dev/~name12/+editsshkeys"> |
2016 | register a SSH key </a>. |
2017 | |
2018 | Click the link and register a key. |
2019 | @@ -149,7 +149,7 @@ |
2020 | >>> instructions = find_tag_by_id(content, 'upload-directions') |
2021 | >>> print instructions.renderContents() |
2022 | Members of <a |
2023 | - href="/~landscape-developers">Landscape |
2024 | + href="http://launchpad.dev/~landscape-developers">Landscape |
2025 | Developers</a> can upload to this branch. <a href="+login">Log in</a> for |
2026 | directions. |
2027 | |
2028 | @@ -161,7 +161,7 @@ |
2029 | >>> instructions = find_tag_by_id(content, 'upload-directions') |
2030 | >>> print instructions.renderContents() |
2031 | You cannot upload to this branch. Members of <a |
2032 | - href="/~landscape-developers">Landscape |
2033 | + href="http://launchpad.dev/~landscape-developers">Landscape |
2034 | Developers</a> can upload to this branch. |
2035 | |
2036 | Finally, if the user is a member of the team, we display the same "you can |
2037 | |
2038 | === modified file 'lib/lp/code/templates/project-branches.pt' |
2039 | --- lib/lp/code/templates/project-branches.pt 2009-07-17 17:59:07 +0000 |
2040 | +++ lib/lp/code/templates/project-branches.pt 2009-08-10 19:04:22 +0000 |
2041 | @@ -6,24 +6,22 @@ |
2042 | xml:lang="en" |
2043 | lang="en" |
2044 | dir="ltr" |
2045 | - metal:use-macro="context/@@main_template/master" |
2046 | + metal:use-macro="view/macro:page/onecolumn" |
2047 | i18n:domain="launchpad" |
2048 | > |
2049 | |
2050 | <body> |
2051 | |
2052 | -<metal:leftportlets fill-slot="portlets_one"> |
2053 | -</metal:leftportlets> |
2054 | - |
2055 | -<metal:rightportlets fill-slot="portlets_two"> |
2056 | -</metal:rightportlets> |
2057 | - |
2058 | -<metal:heading fill-slot="pageheading"> |
2059 | +<div metal:fill-slot="main" tal:define="branches view/branches"> |
2060 | + |
2061 | + <div style="float:right" id="floating-links" |
2062 | + tal:define="menu context/menu:overview"> |
2063 | + <div tal:define="link menu/branch_visibility" |
2064 | + tal:condition="link/enabled" |
2065 | + tal:content="structure link/render" /> |
2066 | + </div> |
2067 | + |
2068 | <h1>Bazaar branches for <tal:project-name replace="context/displayname"/></h1> |
2069 | -</metal:heading> |
2070 | - |
2071 | -<div metal:fill-slot="main" |
2072 | - tal:define="branches view/branches"> |
2073 | |
2074 | <tal:branchlisting content="structure branches/@@+branch-listing" /> |
2075 | |
2076 | |
2077 | === modified file 'lib/lp/registry/browser/configure.zcml' |
2078 | --- lib/lp/registry/browser/configure.zcml 2009-08-12 13:20:10 +0000 |
2079 | +++ lib/lp/registry/browser/configure.zcml 2009-08-14 00:52:28 +0000 |
2080 | @@ -480,8 +480,11 @@ |
2081 | <browser:menus |
2082 | classes=" |
2083 | ProjectFacets |
2084 | + ProjectActionMenu |
2085 | + ProjectEditNavigationMenu |
2086 | ProjectOverviewMenu |
2087 | ProjectBountiesMenu |
2088 | + ProjectBugsMenu |
2089 | ProjectSeriesSpecificationsMenu |
2090 | ProjectSpecificationsMenu |
2091 | ProjectSetContextMenu |
2092 | |
2093 | === modified file 'lib/lp/registry/browser/project.py' |
2094 | --- lib/lp/registry/browser/project.py 2009-08-05 01:49:41 +0000 |
2095 | +++ lib/lp/registry/browser/project.py 2009-08-13 18:10:15 +0000 |
2096 | @@ -13,12 +13,14 @@ |
2097 | 'ProjectBountiesMenu', |
2098 | 'ProjectBrandingView', |
2099 | 'ProjectBreadcrumbBuilder', |
2100 | + 'ProjectBugsMenu', |
2101 | 'ProjectEditView', |
2102 | 'ProjectFacets', |
2103 | 'ProjectMaintainerReassignmentView', |
2104 | 'ProjectNavigation', |
2105 | 'ProjectRdfView', |
2106 | 'ProjectReviewView', |
2107 | + 'ProjectActionMenu', |
2108 | 'ProjectOverviewMenu', |
2109 | 'ProjectSeriesSpecificationsMenu', |
2110 | 'ProjectSetBreadcrumbBuilder', |
2111 | @@ -34,6 +36,7 @@ |
2112 | from zope.component import getUtility |
2113 | from zope.event import notify |
2114 | from zope.formlib import form |
2115 | +from zope.interface import implements, Interface |
2116 | from zope.schema import Choice |
2117 | |
2118 | from z3c.ptcompat import ViewPageTemplateFile |
2119 | @@ -41,6 +44,7 @@ |
2120 | from canonical.cachedproperty import cachedproperty |
2121 | from canonical.launchpad import _ |
2122 | from canonical.launchpad.webapp.interfaces import NotFoundError |
2123 | +from canonical.launchpad.webapp.menu import NavigationMenu |
2124 | from lp.registry.interfaces.product import IProductSet |
2125 | from lp.registry.interfaces.project import ( |
2126 | IProject, IProjectSeries, IProjectSet) |
2127 | @@ -137,41 +141,33 @@ |
2128 | def bugs(self): |
2129 | site = 'bugs' |
2130 | text = 'Bugs' |
2131 | - |
2132 | return Link('', text, enabled=self.context.hasProducts(), site=site) |
2133 | |
2134 | def answers(self): |
2135 | site = 'answers' |
2136 | text = 'Answers' |
2137 | - |
2138 | return Link('', text, enabled=self.context.hasProducts(), site=site) |
2139 | |
2140 | def specifications(self): |
2141 | site = 'blueprints' |
2142 | text = 'Blueprints' |
2143 | - |
2144 | return Link('', text, enabled=self.context.hasProducts(), site=site) |
2145 | |
2146 | def translations(self): |
2147 | site = 'translations' |
2148 | text = 'Translations' |
2149 | - |
2150 | return Link('', text, enabled=self.context.hasProducts(), site=site) |
2151 | |
2152 | |
2153 | -class ProjectOverviewMenu(ApplicationMenu): |
2154 | - |
2155 | - usedfor = IProject |
2156 | - facet = 'overview' |
2157 | - links = [ |
2158 | - 'edit', 'branding', 'driver', 'reassign', 'top_contributors', |
2159 | - 'mentorship', 'announce', 'announcements', 'administer', |
2160 | - 'branch_visibility', 'rdf', 'subscribe'] |
2161 | - |
2162 | - @enabled_with_permission('launchpad.Edit') |
2163 | - def edit(self): |
2164 | - text = 'Change details' |
2165 | - return Link('+edit', text, icon='edit') |
2166 | +class ProjectAdminMenuMixin: |
2167 | + |
2168 | + @enabled_with_permission('launchpad.Admin') |
2169 | + def administer(self): |
2170 | + text = 'Administer' |
2171 | + return Link('+review', text, icon='edit') |
2172 | + |
2173 | + |
2174 | +class ProjectEditMenuMixin(ProjectAdminMenuMixin): |
2175 | |
2176 | @enabled_with_permission('launchpad.Edit') |
2177 | def branding(self): |
2178 | @@ -181,14 +177,30 @@ |
2179 | @enabled_with_permission('launchpad.Edit') |
2180 | def reassign(self): |
2181 | text = 'Change maintainer' |
2182 | - return Link('+reassign', text, icon='edit') |
2183 | + summary = 'Change the maintainer of this project group' |
2184 | + return Link('+reassign', text, summary, icon='edit') |
2185 | |
2186 | @enabled_with_permission('launchpad.Edit') |
2187 | def driver(self): |
2188 | text = 'Appoint driver' |
2189 | - summary = 'Someone with permission to set goals for all projects' |
2190 | + summary = 'Appoint the driver of this project group' |
2191 | return Link('+driver', text, summary, icon='edit') |
2192 | |
2193 | + |
2194 | +class ProjectOverviewMenu(ProjectEditMenuMixin, ApplicationMenu): |
2195 | + |
2196 | + usedfor = IProject |
2197 | + facet = 'overview' |
2198 | + links = [ |
2199 | + 'branding', 'driver', 'reassign', 'top_contributors', 'mentorship', |
2200 | + 'announce', 'announcements', 'branch_visibility', 'rdf', |
2201 | + 'new_product', 'administer', 'milestones'] |
2202 | + |
2203 | + @enabled_with_permission('launchpad.Edit') |
2204 | + def new_product(self): |
2205 | + text = 'Register another project in %s' % self.context.displayname |
2206 | + return Link('+newproduct', text, icon='edit') |
2207 | + |
2208 | def top_contributors(self): |
2209 | text = 'More contributors' |
2210 | return Link('+topcontributors', text, icon='info') |
2211 | @@ -213,26 +225,59 @@ |
2212 | enabled = bool(self.context.getAnnouncements()) |
2213 | return Link('+announcements', text, enabled=enabled) |
2214 | |
2215 | + def milestones(self): |
2216 | + text = 'See all milestones' |
2217 | + return Link('+milestones', text) |
2218 | + |
2219 | def rdf(self): |
2220 | text = structured( |
2221 | 'Download <abbr title="Resource Description Framework">' |
2222 | 'RDF</abbr> metadata') |
2223 | - return Link('+rdf', text, icon='download') |
2224 | - |
2225 | - @enabled_with_permission('launchpad.Admin') |
2226 | - def administer(self): |
2227 | - text = 'Administer' |
2228 | - return Link('+review', text, icon='edit') |
2229 | + return Link('+rdf', text, icon='download-icon') |
2230 | |
2231 | @enabled_with_permission('launchpad.Admin') |
2232 | def branch_visibility(self): |
2233 | text = 'Define branch visibility' |
2234 | return Link('+branchvisibility', text, icon='edit', site='mainsite') |
2235 | |
2236 | + |
2237 | +class IProjectActionMenu(Interface): |
2238 | + """Marker interface for views that use ProjectActionMenu.""" |
2239 | + |
2240 | + |
2241 | +class ProjectActionMenu(ProjectAdminMenuMixin, NavigationMenu): |
2242 | + |
2243 | + usedfor = IProjectActionMenu |
2244 | + facet = 'overview' |
2245 | + title = 'Action menu' |
2246 | + links = ('subscribe', 'edit', 'administer') |
2247 | + |
2248 | + # XXX: salgado, bug=412178, 2009-08-10: This should be shown in the +index |
2249 | + # page of the project's bugs facet, but that would require too much work |
2250 | + # and I just want to convert this page to 3.0, so I'll leave it here for |
2251 | + # now. |
2252 | def subscribe(self): |
2253 | text = 'Subscribe to bug mail' |
2254 | return Link('+subscribe', text, icon='edit') |
2255 | |
2256 | + @enabled_with_permission('launchpad.Edit') |
2257 | + def edit(self): |
2258 | + text = 'Change details' |
2259 | + return Link('+edit', text, icon='edit') |
2260 | + |
2261 | + |
2262 | +class IProjectEditMenu(Interface): |
2263 | + """A marker interface for the 'Change details' navigation menu.""" |
2264 | + |
2265 | + |
2266 | +class ProjectEditNavigationMenu(NavigationMenu, ProjectEditMenuMixin): |
2267 | + """A sub-menu for different aspects of editing a Project's details.""" |
2268 | + |
2269 | + usedfor = IProjectEditMenu |
2270 | + facet = 'overview' |
2271 | + title = 'Change project group' |
2272 | + links = ('branding', 'reassign', 'driver', 'administer') |
2273 | + |
2274 | |
2275 | class ProjectBountiesMenu(ApplicationMenu): |
2276 | |
2277 | @@ -286,12 +331,24 @@ |
2278 | return Link('+addquestion', text, icon='add') |
2279 | |
2280 | |
2281 | +class ProjectBugsMenu(ApplicationMenu): |
2282 | + |
2283 | + usedfor = IProject |
2284 | + facet = 'bugs' |
2285 | + links = ['new'] |
2286 | + |
2287 | + def new(self): |
2288 | + text = 'Report a Bug' |
2289 | + return Link('+filebug', text, icon='add') |
2290 | + |
2291 | + |
2292 | class ProjectView(HasAnnouncementsView, FeedsMixin): |
2293 | - pass |
2294 | + implements(IProjectActionMenu) |
2295 | |
2296 | |
2297 | class ProjectEditView(LaunchpadEditFormView): |
2298 | """View class that lets you edit a Project object.""" |
2299 | + implements(IProjectEditMenu) |
2300 | |
2301 | label = "Change project group details" |
2302 | schema = IProject |
2303 | |
2304 | === modified file 'lib/lp/registry/browser/tests/project-add-views.txt' |
2305 | --- lib/lp/registry/browser/tests/project-add-views.txt 2009-05-12 08:11:06 +0000 |
2306 | +++ lib/lp/registry/browser/tests/project-add-views.txt 2009-08-13 19:36:01 +0000 |
2307 | @@ -310,4 +310,5 @@ |
2308 | |
2309 | >>> for error in view.errors: |
2310 | ... print error |
2311 | - ('name', 'URL', badger is already used by another project) |
2312 | + ('name', 'URL', |
2313 | + LaunchpadValidationError(u'badger is already used by another project')) |
2314 | |
2315 | === modified file 'lib/lp/registry/doc/product-widgets.txt' |
2316 | --- lib/lp/registry/doc/product-widgets.txt 2009-07-01 13:16:44 +0000 |
2317 | +++ lib/lp/registry/doc/product-widgets.txt 2009-08-13 19:36:01 +0000 |
2318 | @@ -301,7 +301,7 @@ |
2319 | |
2320 | |
2321 | >>> license_widget.getInputValue() |
2322 | - Set([<DBItem License.GNU_GPL_V2, (130) ...>]) |
2323 | + set([<DBItem License.GNU_GPL_V2, (130) ...>]) |
2324 | |
2325 | >>> print_checked_items(license_widget()) |
2326 | [ ] Apache License ... |
2327 | |
2328 | === modified file 'lib/lp/registry/interfaces/product.py' |
2329 | --- lib/lp/registry/interfaces/product.py 2009-08-10 17:08:27 +0000 |
2330 | +++ lib/lp/registry/interfaces/product.py 2009-08-13 15:22:00 +0000 |
2331 | @@ -24,7 +24,6 @@ |
2332 | |
2333 | |
2334 | import re |
2335 | -import sets |
2336 | |
2337 | from textwrap import dedent |
2338 | |
2339 | @@ -955,8 +954,7 @@ |
2340 | title=_('Licenses'), |
2341 | value_type=Choice(vocabulary=License), |
2342 | required=False, |
2343 | - # Zope requires sets.Set() instead of the builtin set(). |
2344 | - default=sets.Set( |
2345 | + default=set( |
2346 | [License.OTHER_PROPRIETARY, License.OTHER_OPEN_SOURCE])) |
2347 | |
2348 | has_zero_licenses = Choice( |
2349 | |
2350 | === modified file 'lib/lp/registry/stories/announcements/xx-announcements.txt' |
2351 | --- lib/lp/registry/stories/announcements/xx-announcements.txt 2009-08-11 17:32:21 +0000 |
2352 | +++ lib/lp/registry/stories/announcements/xx-announcements.txt 2009-08-13 18:10:15 +0000 |
2353 | @@ -265,7 +265,7 @@ |
2354 | |
2355 | >>> anon_browser.open('http://launchpad.dev/apache') |
2356 | >>> count_show_links(anon_browser.contents) |
2357 | - 2 |
2358 | + 1 |
2359 | >>> anon_browser.open('http://launchpad.dev/tomcat') |
2360 | >>> count_show_links(anon_browser.contents) |
2361 | 1 |
2362 | |
2363 | === modified file 'lib/lp/registry/stories/distribution/xx-distribution-countrymirrors.txt' |
2364 | --- lib/lp/registry/stories/distribution/xx-distribution-countrymirrors.txt 2009-07-23 13:44:13 +0000 |
2365 | +++ lib/lp/registry/stories/distribution/xx-distribution-countrymirrors.txt 2009-08-05 18:52:52 +0000 |
2366 | @@ -60,5 +60,5 @@ |
2367 | >>> browser.open('http://launchpad.dev/debian/+countrymirrors-archive') |
2368 | Traceback (most recent call last): |
2369 | ... |
2370 | - HTTPError: HTTP Error 404: Not Found |
2371 | + httperror_seek_wrapper: HTTP Error 404: Not Found |
2372 | |
2373 | |
2374 | === modified file 'lib/lp/registry/stories/gpg-coc/98-cocacknowledge.txt' |
2375 | --- lib/lp/registry/stories/gpg-coc/98-cocacknowledge.txt 2009-05-12 01:39:29 +0000 |
2376 | +++ lib/lp/registry/stories/gpg-coc/98-cocacknowledge.txt 2009-08-13 21:32:59 +0000 |
2377 | @@ -24,12 +24,8 @@ |
2378 | >>> admin_browser.getControl(name='searchfor').value = ["all"] |
2379 | >>> admin_browser.getControl(name='name').value = "mark" |
2380 | >>> admin_browser.getControl(name='search').click() |
2381 | - >>> 'paper submission accepted by Foo Bar' in admin_browser.contents |
2382 | - True |
2383 | - >>> '<a href="http://launchpad.dev/~sabdfl"' in admin_browser.contents |
2384 | - True |
2385 | - >>> '[ACTIVE]' in admin_browser.contents |
2386 | - True |
2387 | + >>> print extract_text(find_tag_by_id(admin_browser.contents, 'matches')) |
2388 | + Mark ... paper submission accepted by Foo Bar [ACTIVE] |
2389 | |
2390 | Test if the advertisement email was sent: |
2391 | |
2392 | |
2393 | === modified file 'lib/lp/registry/stories/mailinglists/lifecycle.txt' |
2394 | --- lib/lp/registry/stories/mailinglists/lifecycle.txt 2009-07-23 13:44:13 +0000 |
2395 | +++ lib/lp/registry/stories/mailinglists/lifecycle.txt 2009-08-06 19:11:48 +0000 |
2396 | @@ -580,7 +580,7 @@ |
2397 | >>> admin_browser.getControl(name='field.aardvarks').value = ['approve'] |
2398 | >>> admin_browser.getControl('Submit').click() |
2399 | >>> act() |
2400 | - >>> browser.reload() |
2401 | + >>> browser.open(browser.url) # A `reload` would resubmit. |
2402 | >>> browser.getLink('Mailing list archive') |
2403 | <Link text='Mailing list archive' |
2404 | url='http://lists.launchpad.dev/aardvarks'> |
2405 | @@ -618,7 +618,7 @@ |
2406 | >>> admin_browser.getControl(name='field.antelopes').value = ['approve'] |
2407 | >>> admin_browser.getControl('Submit').click() |
2408 | >>> act() |
2409 | - >>> user_browser.reload() |
2410 | + >>> user_browser.open(user_browser.url) # A `reload` would resubmit. |
2411 | >>> user_browser.getLink('Mailing list archive') |
2412 | <Link text='Mailing list archive' |
2413 | url='http://lists.launchpad.dev/antelopes'> |
2414 | |
2415 | === modified file 'lib/lp/registry/stories/milestone/object-milestones.txt' |
2416 | --- lib/lp/registry/stories/milestone/object-milestones.txt 2009-08-12 01:12:12 +0000 |
2417 | +++ lib/lp/registry/stories/milestone/object-milestones.txt 2009-08-14 00:52:28 +0000 |
2418 | @@ -88,7 +88,9 @@ |
2419 | |
2420 | === Projects === |
2421 | |
2422 | -The main project page has a portlet "Active milestones": |
2423 | +The project "All milestones" page lists all milestones for all products and |
2424 | +series, including the inactive ones. They do not include the bug and blueprint |
2425 | +counts (because they are costly to retrieve). |
2426 | |
2427 | >>> from canonical.launchpad.ftests import login, logout |
2428 | >>> from lp.registry.tests.test_project_milestone import ( |
2429 | @@ -98,15 +100,6 @@ |
2430 | >>> test_helper.setUpProjectMilestoneTests() |
2431 | >>> logout() |
2432 | >>> anon_browser.open('http://launchpad.dev/gnome') |
2433 | - >>> print milestones_in_portlet(anon_browser) |
2434 | - 2011-04-01 1.2 |
2435 | - 2010-04-02 1.1. |
2436 | - 2010-04-01 1.1 |
2437 | - |
2438 | -The project "All milestones" page lists all milestones for all products and |
2439 | -series, including the inactive ones. They do not include the bug and blueprint |
2440 | -counts (because they are costly to retrieve). |
2441 | - |
2442 | >>> anon_browser.getLink('See all milestones').click() |
2443 | >>> print all_milestones(anon_browser) |
2444 | GNOME 2.1.6 None This is an inactive milestone |
2445 | |
2446 | === modified file 'lib/lp/registry/stories/product/xx-launchpad-project-search.txt' |
2447 | --- lib/lp/registry/stories/product/xx-launchpad-project-search.txt 2009-06-11 19:21:46 +0000 |
2448 | +++ lib/lp/registry/stories/product/xx-launchpad-project-search.txt 2009-08-14 03:21:52 +0000 |
2449 | @@ -118,7 +118,7 @@ |
2450 | |
2451 | >>> anon_browser.open('http://launchpad.dev/projects?text=ubuntu') |
2452 | >>> print_search_results(anon_browser) |
2453 | - sprite distribution Ubuntu |
2454 | + bg-image Ubuntu |
2455 | sprite distribution ubuntutest |
2456 | sprite product Evolution |
2457 | sprite product Tomcat |
2458 | |
2459 | === modified file 'lib/lp/registry/stories/project/xx-project-driver.txt' |
2460 | --- lib/lp/registry/stories/project/xx-project-driver.txt 2008-07-02 12:51:24 +0000 |
2461 | +++ lib/lp/registry/stories/project/xx-project-driver.txt 2009-08-13 18:10:15 +0000 |
2462 | @@ -26,6 +26,6 @@ |
2463 | |
2464 | Sample Person is listed as the driver of the project. |
2465 | |
2466 | - >>> for tag in find_tags_by_class(browser.contents, 'summary'): |
2467 | - ... tag.find(text='Driver:').findNext('a').string |
2468 | - u'Sample Person' |
2469 | + >>> print extract_text(find_tag_by_id(browser.contents, 'driver')) |
2470 | + Driver: Sample Person |
2471 | + Appoint driver |
2472 | |
2473 | === modified file 'lib/lp/registry/stories/project/xx-project-edit.txt' |
2474 | --- lib/lp/registry/stories/project/xx-project-edit.txt 2009-08-01 00:02:55 +0000 |
2475 | +++ lib/lp/registry/stories/project/xx-project-edit.txt 2009-08-13 18:10:15 +0000 |
2476 | @@ -53,21 +53,20 @@ |
2477 | |
2478 | The project summary shows the status as reviewed for admins only. |
2479 | |
2480 | - >>> for tag in find_tags_by_class(admin_browser.contents, 'summary'): |
2481 | - ... print extract_text( |
2482 | - ... tag.find(text='Project group status:').findParent('tr')) |
2483 | - Project group status: |
2484 | - Active |
2485 | - Reviewed |
2486 | + >>> print extract_text(find_tag_by_id(admin_browser.contents, 'status')) |
2487 | + Status: Active Reviewed |
2488 | |
2489 | Other users cannot see the Project group status in the details portlet. |
2490 | |
2491 | >>> anon_browser.open('http://launchpad.dev/new-name') |
2492 | >>> print extract_text( |
2493 | ... find_tag_by_id(anon_browser.contents, 'portlet-details')) |
2494 | + Project group information |
2495 | Maintainer: Sample Person |
2496 | Driver: Not yet appointed |
2497 | Bug tracker: The Mozilla.org Bug Tracker |
2498 | + Registered ... by Sample Person |
2499 | + Download RDF metadata |
2500 | |
2501 | Administrators can also change the maintainer and registrant independent |
2502 | of each other, as well as adding aliases to the project group. |
2503 | @@ -90,17 +89,14 @@ |
2504 | |
2505 | The project maintainer and registrant are now updated. |
2506 | |
2507 | - >>> for tag in find_tags_by_class(admin_browser.contents, 'summary'): |
2508 | - ... print extract_text( |
2509 | - ... tag.find(text='Maintainer:').findParent('tr')) |
2510 | - Maintainer: |
2511 | - Celso Providelo |
2512 | + >>> print extract_text( |
2513 | + ... find_tag_by_id(admin_browser.contents, 'maintainer')) |
2514 | + Maintainer: Celso Providelo |
2515 | + Change maintainer |
2516 | |
2517 | - >>> tag = find_tag_by_id(admin_browser.contents, 'portlet-lifecycle') |
2518 | >>> print extract_text( |
2519 | - ... tag.find(text='Registered by:').findParent('tr')) |
2520 | - Registered by: |
2521 | - David Allouche |
2522 | + ... find_tag_by_id(admin_browser.contents, 'registrant')) |
2523 | + Registered ... by David Allouche |
2524 | |
2525 | The registrant really should only be a person, not a team, but that |
2526 | constraint has to be relaxed to account for old data where we do have |
2527 | @@ -111,15 +107,6 @@ |
2528 | >>> admin_browser.getControl('Registrant').value = 'registry' |
2529 | >>> admin_browser.getControl('Change').click() |
2530 | |
2531 | - >>> for tag in find_tags_by_class(admin_browser.contents, 'summary'): |
2532 | - ... print extract_text( |
2533 | - ... tag.find(text='Maintainer:').findParent('tr')) |
2534 | - Maintainer: |
2535 | - Celso Providelo |
2536 | - |
2537 | - >>> tag = find_tag_by_id(admin_browser.contents, 'portlet-lifecycle') |
2538 | >>> print extract_text( |
2539 | - ... tag.find(text='Registered by:').findParent('tr')) |
2540 | - Registered by: |
2541 | - Registry Administrators |
2542 | - |
2543 | + ... find_tag_by_id(admin_browser.contents, 'registrant')) |
2544 | + Registered ... by Registry Administrators |
2545 | |
2546 | === modified file 'lib/lp/registry/stories/project/xx-project-index.txt' |
2547 | --- lib/lp/registry/stories/project/xx-project-index.txt 2009-08-11 17:32:21 +0000 |
2548 | +++ lib/lp/registry/stories/project/xx-project-index.txt 2009-08-13 18:10:15 +0000 |
2549 | @@ -23,28 +23,28 @@ |
2550 | >>> anon_browser.title |
2551 | 'The GNOME Project in Launchpad' |
2552 | |
2553 | -The page lists the member projects. |
2554 | +The page lists the member projects, together with the releases/milestones of |
2555 | +its development focus. |
2556 | |
2557 | >>> print extract_text(find_tag_by_id(anon_browser.contents, 'products')) |
2558 | Projects |
2559 | Gnome Applets ... |
2560 | Evolution ... |
2561 | - Releases: 2.1.6 |
2562 | + trunk series: 2.1.6, |
2563 | GNOME Terminal ... |
2564 | - Milestones: 2.30.0 |
2565 | gnomebaker ... |
2566 | - Releases: 2.1.7 |
2567 | - Milestones: 2.30.1, 2.1.7 |
2568 | + trunk series: 2.1.7, 2.1.7 |
2569 | NetApplet ... |
2570 | - Releases: 1.0 |
2571 | + trunk series: 1.0, |
2572 | + ... |
2573 | |
2574 | And the projects, milestone, and releases are linked. |
2575 | |
2576 | >>> print anon_browser.getLink('gnomebaker').url |
2577 | http://launchpad.dev/gnomebaker |
2578 | |
2579 | - >>> print anon_browser.getLink('2.30.1').url |
2580 | - http://launchpad.dev/gnomebaker/+milestone/2.30.1 |
2581 | + >>> print anon_browser.getLink('1.0').url |
2582 | + http://launchpad.dev/netapplet/trunk/1.0 |
2583 | |
2584 | >>> print anon_browser.getLink('2.1.7').url |
2585 | http://launchpad.dev/gnomebaker/trunk/2.1.7 |
2586 | |
2587 | === modified file 'lib/lp/registry/templates/codeofconduct-admin.pt' |
2588 | --- lib/lp/registry/templates/codeofconduct-admin.pt 2009-07-22 14:19:22 +0000 |
2589 | +++ lib/lp/registry/templates/codeofconduct-admin.pt 2009-08-13 21:32:59 +0000 |
2590 | @@ -71,7 +71,7 @@ |
2591 | <tal:results condition="view/search"> |
2592 | <h2>Results</h2> |
2593 | |
2594 | - <ul tal:condition="view/results"> |
2595 | + <ul id="matches" tal:condition="view/results"> |
2596 | <li tal:repeat="code view/results"> |
2597 | <a tal:replace="structure code/owner/fmt:link">OWNER</a> |
2598 | <a tal:attributes="href code/id" |
2599 | |
2600 | === modified file 'lib/lp/registry/templates/project-details.pt' |
2601 | --- lib/lp/registry/templates/project-details.pt 2009-07-17 17:59:07 +0000 |
2602 | +++ lib/lp/registry/templates/project-details.pt 2009-08-13 18:10:15 +0000 |
2603 | @@ -4,53 +4,62 @@ |
2604 | xmlns:i18n="http://xml.zope.org/namespaces/i18n" |
2605 | omit-tag=""> |
2606 | |
2607 | -<div class="portlet" id="portlet-details"> |
2608 | - <div class="portletBody portletContent"> |
2609 | - <table class="summary"> |
2610 | - <tbody> |
2611 | - <tr tal:condition="context/required:launchpad.Admin"> |
2612 | - <th>Project group status:</th> |
2613 | - <td> |
2614 | - <tal:block condition="context/active">Active</tal:block> |
2615 | - <tal:block condition="not: context/active">Disabled</tal:block> |
2616 | - <tal:block condition="context/reviewed"><br />Reviewed</tal:block> |
2617 | - <tal:block condition="context/icon"><br />Branded |
2618 | - <tal:icon replace="structure context/image:icon" /> |
2619 | - </tal:block> |
2620 | - </td> |
2621 | - </tr> |
2622 | - <tr> |
2623 | - <th>Maintainer:</th> |
2624 | - <td> |
2625 | - <a |
2626 | - tal:content="context/owner/displayname" |
2627 | - tal:attributes="href context/owner/fmt:url" |
2628 | - >ownername</a> |
2629 | - </td> |
2630 | - </tr> |
2631 | - <tr> |
2632 | - <th>Driver:</th> |
2633 | - <td tal:condition="not:context/driver">Not yet appointed</td> |
2634 | - <td tal:condition="context/driver"> |
2635 | - <a |
2636 | - tal:content="context/driver/displayname" |
2637 | - tal:attributes="href context/driver/fmt:url" |
2638 | - >Carlos Perello</a> |
2639 | - </td> |
2640 | - </tr> |
2641 | - <tr> |
2642 | - <th>Bug tracker:</th> |
2643 | - <td> |
2644 | - <a |
2645 | - tal:condition="context/bugtracker" |
2646 | - tal:content="context/bugtracker/title" |
2647 | - tal:attributes="href context/bugtracker/fmt:url" |
2648 | - >tracker title</a> |
2649 | - <tal:none condition="not:context/bugtracker">None specified</tal:none> |
2650 | - </td> |
2651 | - </tr> |
2652 | - </tbody> |
2653 | - </table> |
2654 | +<div id="portlet-details" class="portlet"> |
2655 | + <h2>Project group information</h2> |
2656 | + <div class="two-column-list" tal:define="overview_menu context/menu:overview"> |
2657 | + <dl tal:condition="context/required:launchpad.Admin" id="status"> |
2658 | + <dt>Status:</dt> |
2659 | + <dd> |
2660 | + <tal:block condition="context/active">Active</tal:block> |
2661 | + <tal:block condition="not: context/active">Disabled</tal:block> |
2662 | + <tal:block condition="context/reviewed"><br />Reviewed</tal:block> |
2663 | + <tal:block condition="context/icon"><br />Branded |
2664 | + <tal:icon replace="structure context/image:icon" /> |
2665 | + </tal:block> |
2666 | + </dd> |
2667 | + </dl> |
2668 | + <dl id="maintainer"> |
2669 | + <dt>Maintainer:</dt> |
2670 | + <dd> |
2671 | + <a tal:replace="structure context/owner/fmt:link" /> |
2672 | + <tal:edit-maintainer |
2673 | + content="structure overview_menu/reassign/fmt:icon" /> |
2674 | + </dd> |
2675 | + </dl> |
2676 | + <dl id="driver"> |
2677 | + <dt>Driver:</dt> |
2678 | + <dd> |
2679 | + <tal:no-driver condition="not:context/driver"> |
2680 | + Not yet appointed |
2681 | + </tal:no-driver> |
2682 | + <tal:has-driver condition="context/driver"> |
2683 | + <a tal:replace="structure context/driver/fmt:link">Driver</a> |
2684 | + </tal:has-driver> |
2685 | + <tal:edit-maintainer |
2686 | + content="structure overview_menu/driver/fmt:icon" /> |
2687 | + </dd> |
2688 | + </dl> |
2689 | + <dl id="bug-tracker"> |
2690 | + <dt>Bug tracker:</dt> |
2691 | + <dd> |
2692 | + <a |
2693 | + tal:condition="context/bugtracker" |
2694 | + tal:content="context/bugtracker/title" |
2695 | + tal:attributes="href context/bugtracker/fmt:url" |
2696 | + >tracker title</a> |
2697 | + <tal:none condition="not:context/bugtracker">None specified</tal:none> |
2698 | + </dd> |
2699 | + </dl> |
2700 | </div> |
2701 | + <p id="registrant"> |
2702 | + Registered |
2703 | + <tal:created replace="context/datecreated/fmt:approximatedate" /> |
2704 | + by <tal:registrant replace="structure context/registrant/fmt:link" /> |
2705 | + </p> |
2706 | + <ul class="horizontal"> |
2707 | + <li> |
2708 | + <a tal:replace="structure context/menu:overview/rdf/fmt:link-icon" /> |
2709 | + </li> |
2710 | + </ul> |
2711 | </div> |
2712 | </tal:root> |
2713 | |
2714 | === modified file 'lib/lp/registry/templates/project-edit.pt' |
2715 | --- lib/lp/registry/templates/project-edit.pt 2009-07-18 00:05:49 +0000 |
2716 | +++ lib/lp/registry/templates/project-edit.pt 2009-08-05 19:26:37 +0000 |
2717 | @@ -3,20 +3,14 @@ |
2718 | xmlns:tal="http://xml.zope.org/namespaces/tal" |
2719 | xmlns:metal="http://xml.zope.org/namespaces/metal" |
2720 | xmlns:i18n="http://xml.zope.org/namespaces/i18n" |
2721 | - xml:lang="en" |
2722 | - lang="en" |
2723 | - dir="ltr" |
2724 | - metal:use-macro="context/@@main_template/master" |
2725 | + metal:use-macro="view/macro:page/main_only" |
2726 | i18n:domain="launchpad" |
2727 | > |
2728 | <body> |
2729 | - <metal:heading fill-slot="heading"> |
2730 | - <h1>Change project group details</h1> |
2731 | - </metal:heading> |
2732 | - |
2733 | <div metal:fill-slot="main"> |
2734 | |
2735 | - <div metal:use-macro="context/@@launchpad_form/form"> |
2736 | + <div class="top-portlet" |
2737 | + metal:use-macro="context/@@launchpad_form/form"> |
2738 | |
2739 | <p metal:fill-slot="extra_info"> |
2740 | Avoid changing the Name, |
2741 | @@ -28,6 +22,7 @@ |
2742 | |
2743 | </div> |
2744 | |
2745 | + <tal:menu replace="structure view/@@+related-pages" /> |
2746 | </div> |
2747 | |
2748 | </body> |
2749 | |
2750 | === modified file 'lib/lp/registry/templates/project-index.pt' |
2751 | --- lib/lp/registry/templates/project-index.pt 2009-07-17 17:59:07 +0000 |
2752 | +++ lib/lp/registry/templates/project-index.pt 2009-08-13 18:10:15 +0000 |
2753 | @@ -3,43 +3,37 @@ |
2754 | xmlns:tal="http://xml.zope.org/namespaces/tal" |
2755 | xmlns:metal="http://xml.zope.org/namespaces/metal" |
2756 | xmlns:i18n="http://xml.zope.org/namespaces/i18n" |
2757 | - xml:lang="en" |
2758 | - lang="en" |
2759 | - dir="ltr" |
2760 | - metal:use-macro="view/macro:page/default" |
2761 | + metal:use-macro="view/macro:page/main_side" |
2762 | i18n:domain="launchpad" |
2763 | > |
2764 | <body> |
2765 | |
2766 | - <metal:portlets fill-slot="portlets"> |
2767 | - <tal:portlet tal:replace="structure context/@@+portlet-lifecycle" /> |
2768 | - <tal:portlet tal:replace="structure context/@@+portlet-milestones" /> |
2769 | - </metal:portlets> |
2770 | - |
2771 | - <div metal:fill-slot="main"> |
2772 | - |
2773 | - <p id="project-inactive" tal:condition="not: context/active" class="warning message"> |
2774 | - This project is currently inactive <a href="+review">(change this)</a> |
2775 | - </p> |
2776 | - |
2777 | - <tal:block condition="view/required:launchpad.Edit"> |
2778 | - <p tal:condition="not: context/products" class="warning message"> |
2779 | - There are no projects registered for |
2780 | - <span tal:replace="context/displayname">project displayname</span>. |
2781 | - <br /> |
2782 | - You need to <a href="+newproduct">register another project that is |
2783 | - part of <tal:project replace="context/displayname" /></a> or associate |
2784 | - an existing project with it. |
2785 | + <tal:heading metal:fill-slot="heading"> |
2786 | + <h1 tal:content="context/title">Mozilla</h1> |
2787 | + </tal:heading> |
2788 | + |
2789 | + <tal:main metal:fill-slot="main"> |
2790 | + |
2791 | + <div class="top-portlet"> |
2792 | + <p id="project-inactive" class="warning message" |
2793 | + tal:condition="not: context/active"> |
2794 | + This project is currently inactive |
2795 | + <a tal:attributes="href context/menu:overview/administer/url" |
2796 | + >(change this)</a> |
2797 | </p> |
2798 | - </tal:block> |
2799 | - |
2800 | - <div |
2801 | - style="width: 200px; height: 200px; float: right;" |
2802 | - tal:content="structure context/image:mugshot" |
2803 | - /> |
2804 | - <h1 tal:content="context/title">Mozilla</h1> |
2805 | - |
2806 | - <div class="description" tal:content="context/summary"> |
2807 | + |
2808 | + <tal:block condition="view/required:launchpad.Edit"> |
2809 | + <p tal:condition="not: context/products" class="warning message"> |
2810 | + There are no projects registered for |
2811 | + <span tal:replace="context/displayname">project displayname</span>. |
2812 | + <br /> |
2813 | + You need to <a href="+newproduct">register another project that is |
2814 | + part of <tal:project replace="context/displayname" /></a> or associate |
2815 | + an existing project with it. |
2816 | + </p> |
2817 | + </tal:block> |
2818 | + |
2819 | + <div class="summary" tal:content="context/summary"> |
2820 | This is the project group Summary, which should be a single paragraph |
2821 | summarising the project group's purpose. |
2822 | </div> |
2823 | @@ -58,92 +52,97 @@ |
2824 | Apache Server, and mention other projects such as APR. |
2825 | </div> |
2826 | |
2827 | - <ul tal:condition="context/homepageurl"> |
2828 | - <li> |
2829 | - <a rel="nofollow" |
2830 | - tal:attributes="href context/homepageurl; |
2831 | - class string:sprite external-link"> |
2832 | - <strong>Visit the <tal:name replace="context/title" /> |
2833 | - home page »</strong> |
2834 | - </a> |
2835 | - </li> |
2836 | - </ul> |
2837 | - <ul class="buttons" tal:condition="context/products"> |
2838 | - <li> |
2839 | - <a href="+filebug"> |
2840 | - <img alt="Report a bug" src="/+icing/but-sml-reportabug.gif" /> |
2841 | - </a> |
2842 | - </li> |
2843 | - <li tal:content="structure context/@@+ask-a-question-button" /> |
2844 | - <li tal:content="structure context/@@+help-translate-button" /> |
2845 | - <li tal:define="has_mentoring context/mentoring_offers/count"> |
2846 | - <a href="+mentoring" tal:condition="has_mentoring"> |
2847 | - <img alt="Mentoring available" |
2848 | - src="/+icing/but-sml-mentoring.gif"/> |
2849 | - </a> |
2850 | - <a href="+mentoring" tal:condition="not: has_mentoring"> |
2851 | - <img alt="No mentoring available" |
2852 | - src="/+icing/but-sml-mentoring-off.gif" /> |
2853 | - </a> |
2854 | - </li> |
2855 | - </ul> |
2856 | - <div class="left"> |
2857 | - <div |
2858 | - class="section" |
2859 | - tal:content="structure context/@@+portlet-coming-sprints" |
2860 | - /> |
2861 | - <div |
2862 | - class="section" |
2863 | - tal:content="structure context/@@+portlet-latestannouncements" |
2864 | - /> |
2865 | - <div class="portlet" id="products"> |
2866 | + <ul id="external-links" class="horizontal" |
2867 | + tal:condition="context/homepageurl"> |
2868 | + <li> |
2869 | + <a rel="nofollow" class="sprite external-link" |
2870 | + tal:attributes="href context/homepageurl">Home page</a> |
2871 | + </li> |
2872 | + </ul> |
2873 | + </div> |
2874 | + |
2875 | + <div class="yui-g"> |
2876 | + <div class="yui-u first"> |
2877 | + <tal:details replace="structure context/@@+details" /> |
2878 | + </div> |
2879 | + <div class="yui-u" id="products"> |
2880 | + <div class="portlet"> |
2881 | <h2>Projects</h2> |
2882 | - <p tal:condition="not: context/products"> |
2883 | + <p tal:condition="not: context/products"> |
2884 | There are no projects registered for |
2885 | <span tal:replace="context/displayname">project displayname</span>. |
2886 | </p> |
2887 | - <div |
2888 | - tal:condition="context/products" |
2889 | - tal:repeat="product context/products"> |
2890 | - <tal:link replace="structure product/fmt:link" /> |
2891 | - <div tal:condition="product/releases/count"> |
2892 | - Releases: |
2893 | - <tal:release repeat="release product/releases"> |
2894 | - <a |
2895 | - tal:attributes="href release/fmt:url" |
2896 | - tal:content="release/version" |
2897 | - >version</a><tal:comma |
2898 | - condition="not:repeat/release/end">,</tal:comma> |
2899 | - </tal:release> |
2900 | - </div> |
2901 | - <div tal:condition="product/milestones"> |
2902 | - Milestones: |
2903 | - <tal:milestone repeat="milestone product/milestones"> |
2904 | - <a |
2905 | - tal:attributes="href milestone/fmt:url" |
2906 | - tal:content="milestone/name" |
2907 | - >name</a><tal:comma |
2908 | - condition="not:repeat/milestone/end">,</tal:comma> |
2909 | - </tal:milestone> |
2910 | - </div> |
2911 | - </div> |
2912 | - <tal:block condition="context/required:launchpad.Edit"> |
2913 | - <a href="+newproduct">» Register another project that is |
2914 | - part of <tal:project replace="context/displayname" /></a> |
2915 | - </tal:block> |
2916 | + <dl tal:condition="context/products" |
2917 | + tal:repeat="product context/products"> |
2918 | + <dt><a tal:replace="structure product/fmt:link">product</a></dt> |
2919 | + <dd tal:define="dev_focus product/development_focus"> |
2920 | + <a tal:attributes="href dev_focus/fmt:url" |
2921 | + tal:content="dev_focus/name">trunk</a> |
2922 | + series: |
2923 | + <tal:releases repeat="release dev_focus/releases"> |
2924 | + <strong> |
2925 | + <a tal:attributes="href release/fmt:url" |
2926 | + tal:content="release/version">release |
2927 | + </a></strong>, |
2928 | + </tal:releases> |
2929 | + <tal:releases repeat="milestone dev_focus/milestones"> |
2930 | + <strong> |
2931 | + <a tal:attributes="href milestone/fmt:url" |
2932 | + tal:content="milestone/name">milestone |
2933 | + </a></strong><tal:comma |
2934 | + condition="not:repeat/milestone/end">,</tal:comma> |
2935 | + </tal:releases> |
2936 | + </dd> |
2937 | + </dl> |
2938 | + <ul> |
2939 | + <li> |
2940 | + <a tal:replace="structure context/menu:overview/milestones/fmt:link" /> |
2941 | + </li> |
2942 | + <li tal:condition="context/menu:overview/new_product/enabled"> |
2943 | + <a tal:replace="structure context/menu:overview/new_product/fmt:link" /> |
2944 | + </li> |
2945 | + </ul> |
2946 | </div> |
2947 | - <div tal:replace="structure context/@@+portlet-latestspecs" /> |
2948 | - </div> |
2949 | - <div class="right"> |
2950 | - <div tal:replace="structure context/@@+details" /> |
2951 | - <div tal:replace="structure context/@@+portlet-top-contributors" /> |
2952 | - <div tal:replace="structure context/@@+portlet-latestbugs" /> |
2953 | - <div |
2954 | - class="section" |
2955 | - tal:content="structure context/@@+portlet-latestquestions" |
2956 | - /> |
2957 | - </div> |
2958 | - </div> |
2959 | + </div> |
2960 | + </div> |
2961 | + <div class="yui-g"> |
2962 | + <div class="yui-u first"> |
2963 | + <tal:bugs content="structure context/@@+portlet-latestbugs" /> |
2964 | + <tal:specs content="structure context/@@+portlet-latestspecs" /> |
2965 | + <tal:sprints content="structure context/@@+portlet-coming-sprints" /> |
2966 | + </div> |
2967 | + <div class="yui-u"> |
2968 | + <tal:questions content="structure context/@@+portlet-latestquestions" /> |
2969 | + <tal:contributors content="structure context/@@+portlet-top-contributors" /> |
2970 | + </div> |
2971 | + </div> |
2972 | + </tal:main> |
2973 | + |
2974 | + <tal:side metal:fill-slot="side"> |
2975 | + <div id="object-actions" class="top-portlet"> |
2976 | + <tal:menu replace="structure view/@@+global-actions" /> |
2977 | + </div> |
2978 | + <div id="involvement" class="portlet involvement" |
2979 | + tal:condition="context/products"> |
2980 | + <h2>Get Involved</h2> |
2981 | + <ul> |
2982 | + <li> |
2983 | + <a class="bugs" |
2984 | + tal:attributes="href context/menu:bugs/new/url">Report a Bug</a> |
2985 | + </li> |
2986 | + <li> |
2987 | + <a class="question" |
2988 | + tal:attributes="href context/menu:answers/new/url">Ask a question</a> |
2989 | + </li> |
2990 | + <li> |
2991 | + <a class="translate" |
2992 | + tal:attributes="href context/menu:translations/overview/url">Help translate</a> |
2993 | + </li> |
2994 | + </ul> |
2995 | + </div> |
2996 | + <tal:portlet tal:replace="structure context/@@+portlet-latestannouncements" /> |
2997 | + </tal:side> |
2998 | + |
2999 | </body> |
3000 | </html> |
3001 | |
3002 | |
3003 | === modified file 'lib/lp/soyuz/browser/tests/archive-views.txt' |
3004 | --- lib/lp/soyuz/browser/tests/archive-views.txt 2009-07-30 01:24:18 +0000 |
3005 | +++ lib/lp/soyuz/browser/tests/archive-views.txt 2009-08-13 19:36:01 +0000 |
3006 | @@ -932,7 +932,9 @@ |
3007 | >>> print archive_widget.getInputValue() |
3008 | Traceback (most recent call last): |
3009 | ... |
3010 | - WidgetInputError: ('destination_archive', u'Destination PPA', ) |
3011 | + WidgetInputError: ('destination_archive', |
3012 | + u'Destination PPA', |
3013 | + RequiredMissing()) |
3014 | |
3015 | |
3016 | === Copy private files to public archives === |
3017 | |
3018 | === modified file 'lib/lp/soyuz/browser/tests/binarypackagerelease-views.txt' |
3019 | --- lib/lp/soyuz/browser/tests/binarypackagerelease-views.txt 2009-08-13 19:20:04 +0000 |
3020 | +++ lib/lp/soyuz/browser/tests/binarypackagerelease-views.txt 2009-08-13 19:51:29 +0000 |
3021 | @@ -1,6 +1,6 @@ |
3022 | = BinaryPackageRelease Pages = |
3023 | |
3024 | - >>> from zope.component import queryMultiAdapter |
3025 | + >>> from zope.component import getMultiAdapter |
3026 | >>> from zope.publisher.browser import TestRequest |
3027 | >>> from canonical.launchpad.database import BinaryPackageRelease |
3028 | |
3029 | @@ -16,7 +16,7 @@ |
3030 | |
3031 | Let's instantiate the view for +portlet-details: |
3032 | |
3033 | - >>> pmount_view = queryMultiAdapter( |
3034 | + >>> pmount_view = getMultiAdapter( |
3035 | ... (pmount_bin, request), name="+portlet-details") |
3036 | |
3037 | Main functionality of this class is to provide abstracted model of the |
3038 | @@ -52,4 +52,3 @@ |
3039 | ('tramp-package', None, '', None) |
3040 | |
3041 | Other relationship groups use the same mechanism. |
3042 | - |
3043 | |
3044 | === modified file 'lib/lp/soyuz/stories/ppa/xx-edit-dependencies.txt' |
3045 | --- lib/lp/soyuz/stories/ppa/xx-edit-dependencies.txt 2009-06-19 16:15:02 +0000 |
3046 | +++ lib/lp/soyuz/stories/ppa/xx-edit-dependencies.txt 2009-08-06 20:16:29 +0000 |
3047 | @@ -142,7 +142,7 @@ |
3048 | |
3049 | Now Celso's PPA will list Mark's and No-Priv's PPA as its dependencies. |
3050 | |
3051 | - >>> admin_browser.reload() |
3052 | + >>> admin_browser.open(admin_browser.url) # Reload will set old form values. |
3053 | >>> print_ppa_dependencies(admin_browser.contents) |
3054 | PPA for Mark Shuttleworth |
3055 | PPA for No Privileges Person |
3056 | |
3057 | === modified file 'lib/lp/translations/browser/project.py' |
3058 | --- lib/lp/translations/browser/project.py 2009-07-17 02:25:09 +0000 |
3059 | +++ lib/lp/translations/browser/project.py 2009-08-05 19:26:37 +0000 |
3060 | @@ -11,7 +11,7 @@ |
3061 | ] |
3062 | |
3063 | from canonical.launchpad.webapp import ( |
3064 | - ApplicationMenu, enabled_with_permission, Link, LaunchpadView) |
3065 | + canonical_url, enabled_with_permission, Link, LaunchpadView) |
3066 | from canonical.launchpad.webapp.menu import NavigationMenu |
3067 | from lp.registry.interfaces.project import IProject |
3068 | |
3069 | @@ -20,7 +20,7 @@ |
3070 | |
3071 | usedfor = IProject |
3072 | facet = 'translations' |
3073 | - links = ['products', 'changetranslators'] |
3074 | + links = ['products', 'changetranslators', 'overview'] |
3075 | |
3076 | @enabled_with_permission('launchpad.Edit') |
3077 | def changetranslators(self): |
3078 | @@ -31,6 +31,11 @@ |
3079 | text = 'Products' |
3080 | return Link('', text) |
3081 | |
3082 | + def overview(self): |
3083 | + text = 'Overview' |
3084 | + link = canonical_url(self.context, rootsite='translations') |
3085 | + return Link(link, text, icon='translation') |
3086 | + |
3087 | |
3088 | class ProjectView(LaunchpadView): |
3089 | pass |
3090 | |
3091 | === modified file 'lib/lp/translations/stories/distroseries/xx-distroseries-translations.txt' |
3092 | --- lib/lp/translations/stories/distroseries/xx-distroseries-translations.txt 2009-07-01 20:45:39 +0000 |
3093 | +++ lib/lp/translations/stories/distroseries/xx-distroseries-translations.txt 2009-07-16 13:28:25 +0000 |
3094 | @@ -101,7 +101,7 @@ |
3095 | ... 'http://translations.launchpad.dev/ubuntu/hoary/+lang/es') |
3096 | Traceback (most recent call last): |
3097 | ... |
3098 | - HTTPError: HTTP Error 503: Service Unavailable |
3099 | + httperror_seek_wrapper: HTTP Error 503: Service Unavailable |
3100 | >>> main_content = find_main_content(user_browser.contents) |
3101 | >>> print main_content.findNext('p').renderContents() |
3102 | Translations for this release series are not available yet. |
3103 | |
3104 | === modified file 'lib/lp/translations/stories/standalone/xx-pofile-translate-html-tags-escape.txt' |
3105 | --- lib/lp/translations/stories/standalone/xx-pofile-translate-html-tags-escape.txt 2009-07-01 20:45:39 +0000 |
3106 | +++ lib/lp/translations/stories/standalone/xx-pofile-translate-html-tags-escape.txt 2009-08-06 11:42:11 +0000 |
3107 | @@ -31,6 +31,5 @@ |
3108 | >>> text = find_tag_by_id( |
3109 | ... user_browser.contents, 'msgset_67_hr_translation_0') |
3110 | >>> print extract_text(text.renderContents()) |
3111 | - Upotreba: |
3112 | - |
3113 | - %s [opcije] <foo> [<etiketa>]%s%s%s |
3114 | + Upotreba: |
3115 | + %s [opcije] <foo> [<etiketa>]%s%s%s |
3116 | |
3117 | === modified file 'lib/lp/translations/stories/translationgroups/30-show-group-translation-targets.txt' |
3118 | --- lib/lp/translations/stories/translationgroups/30-show-group-translation-targets.txt 2009-07-01 13:16:44 +0000 |
3119 | +++ lib/lp/translations/stories/translationgroups/30-show-group-translation-targets.txt 2009-08-13 21:32:59 +0000 |
3120 | @@ -16,7 +16,7 @@ |
3121 | >>> for link in portlet.findAll('a'): |
3122 | ... print '%s: %s' % (link.find(text=True), link['href']) |
3123 | Ubuntu: /ubuntu |
3124 | - NetApplet: http://translations.launchpad.dev/netapplet |
3125 | + NetApplet: /netapplet |
3126 | GNOME: /gnome |
3127 | |
3128 | If we disable some of these projects... |
3129 | |
3130 | === modified file 'lib/lp/translations/templates/translationgroup-portlet-relateds.pt' |
3131 | --- lib/lp/translations/templates/translationgroup-portlet-relateds.pt 2009-07-17 17:59:07 +0000 |
3132 | +++ lib/lp/translations/templates/translationgroup-portlet-relateds.pt 2009-08-13 21:32:59 +0000 |
3133 | @@ -25,7 +25,8 @@ |
3134 | <h3>Projects:</h3> |
3135 | <ul> |
3136 | <li tal:repeat="product context/products"> |
3137 | - <tal:link replace="structure product/fmt:link" /> |
3138 | + <tal:link replace="structure product/fmt:link:translations" /> |
3139 | + <tal:link replace="structure product/fmt:url:translations" /> |
3140 | </li> |
3141 | </ul> |
3142 | </tal:products> |
3143 | |
3144 | === removed symlink 'lib/mechanize' |
3145 | === target was u'../sourcecode/zope/src/mechanize' |
3146 | === removed symlink 'lib/persistent' |
3147 | === target was u'../sourcecode/zope/src/persistent/' |
3148 | === removed symlink 'lib/transaction' |
3149 | === target was u'../sourcecode/zope/src/transaction/' |
3150 | === removed symlink 'lib/twisted' |
3151 | === target was u'../sourcecode/twisted/twisted/' |
3152 | === added symlink 'lib/twisted' |
3153 | === target is u'../sourcecode/twisted/twisted/' |
3154 | === removed directory 'lib/zc' |
3155 | === removed file 'lib/zc/__init__.py' |
3156 | --- lib/zc/__init__.py 2009-01-03 19:32:48 +0000 |
3157 | +++ lib/zc/__init__.py 1970-01-01 00:00:00 +0000 |
3158 | @@ -1,2 +0,0 @@ |
3159 | -# This is a namespace package for zc.* packages. We should absolutely get rid |
3160 | -# of this once we are using eggs. |
3161 | |
3162 | === removed symlink 'lib/zc/zservertracelog' |
3163 | === target was u'../../sourcecode/zc.zservertracelog/src/zc/zservertracelog' |
3164 | === removed symlink 'lib/zdaemon' |
3165 | === target was u'../sourcecode/zope/src/zdaemon/' |
3166 | === removed symlink 'lib/zodbcode' |
3167 | === target was u'../sourcecode/zope/src/zodbcode/' |
3168 | === removed symlink 'lib/zope' |
3169 | === target was u'../sourcecode/zope/src/zope/' |
3170 | === modified file 'setup.py' |
3171 | --- setup.py 2009-07-24 11:14:47 +0000 |
3172 | +++ setup.py 2009-08-05 18:52:52 +0000 |
3173 | @@ -20,26 +20,78 @@ |
3174 | maintainer='Launchpad Developers', |
3175 | description=('A unique collaboration and Bazaar code hosting platform ' |
3176 | 'for software projects.'), |
3177 | - license='LGPL v3', |
3178 | + license='Affero GPL v3', |
3179 | + # this list should only contain direct dependencies--things imported or |
3180 | + # used in zcml. |
3181 | install_requires=[ |
3182 | 'bzr', |
3183 | + 'chameleon.core', |
3184 | + 'chameleon.zpt', |
3185 | 'feedvalidator', |
3186 | 'funkload', |
3187 | 'launchpadlib', |
3188 | 'lazr.smtptest', |
3189 | 'lazr.uri', |
3190 | + 'mechanize', |
3191 | 'mocker', |
3192 | 'oauth', |
3193 | 'python-openid', |
3194 | 'pytz', |
3195 | + # This appears to be a broken indirect dependency from zope.security: |
3196 | + 'RestrictedPython', |
3197 | 'setuptools', |
3198 | 'sourcecodegen', |
3199 | 'storm', |
3200 | - 'chameleon.core', |
3201 | - 'chameleon.zpt', |
3202 | + 'transaction', |
3203 | + 'wadllib', |
3204 | 'z3c.pt', |
3205 | 'z3c.ptcompat', |
3206 | - 'wadllib', |
3207 | + 'zc.zservertracelog', |
3208 | + 'zope.app.appsetup', |
3209 | + 'zope.app.component', |
3210 | + 'zope.app.dav', # ./package-includes/dav-configure.zcml |
3211 | + 'zope.app.error', |
3212 | + 'zope.app.exception', |
3213 | + 'zope.app.file', |
3214 | + 'zope.app.form', |
3215 | + 'zope.app.pagetemplate', |
3216 | + 'zope.app.pluggableauth', |
3217 | + 'zope.app.publication', |
3218 | + 'zope.app.publisher', |
3219 | + 'zope.app.security', |
3220 | + 'zope.app.securitypolicy', |
3221 | + 'zope.app.server', |
3222 | + 'zope.app.session', |
3223 | + 'zope.app.testing', |
3224 | + 'zope.app.wsgi', |
3225 | + 'zope.app.zapi', |
3226 | + 'zope.contenttype', |
3227 | + 'zope.component[zcml]', |
3228 | + 'zope.datetime', |
3229 | + 'zope.thread', |
3230 | + 'zope.error', |
3231 | + 'zope.event', |
3232 | + 'zope.exceptions', |
3233 | + 'zope.formlib', |
3234 | + 'zope.i18n', |
3235 | + 'zope.interface', |
3236 | + 'zope.hookable', # indirect, via zope.app.component |
3237 | + 'zope.lifecycleevent', |
3238 | + 'zope.location', |
3239 | + 'zope.pagetemplate', |
3240 | + 'zope.publisher', |
3241 | + 'zope.proxy', |
3242 | + 'zope.schema', |
3243 | + 'zope.security', |
3244 | + 'zope.sendmail', |
3245 | + 'zope.server', |
3246 | + 'zope.session', |
3247 | + 'zope.tal', |
3248 | + 'zope.tales', |
3249 | + 'zope.testbrowser', |
3250 | + 'zope.testing', |
3251 | + 'zope.traversing', |
3252 | + 'zope.viewlet', # only fixing a broken dependency |
3253 | # Loggerhead dependencies. These should be removed once |
3254 | # bug 383360 is fixed and we include it as a source dist. |
3255 | 'Paste', |
3256 | |
3257 | === modified file 'utilities/sourcedeps.conf' |
3258 | --- utilities/sourcedeps.conf 2009-07-21 07:55:23 +0000 |
3259 | +++ utilities/sourcedeps.conf 2009-08-14 17:26:21 +0000 |
3260 | @@ -18,10 +18,8 @@ |
3261 | testresources=lp:~launchpad-pqm/testresources/dev/ |
3262 | testtools=lp:~launchpad-pqm/testtools/trunk/ |
3263 | twisted=lp:~launchpad-pqm/twisted/trunk/ |
3264 | -zc.zservertracelog=lp:~launchpad-pqm/zc.zservertracelog/trunk/ |
3265 | cscvs=lp:~launchpad-pqm/launchpad-cscvs/devel/ |
3266 | lpreview=lp:~launchpad-pqm/bzr-lpreview/devel/ |
3267 | -zope=lp:~launchpad-pqm/zope3/3.4/ |
3268 | pygettextpo=lp:~launchpad/pygettextpo/trunk/ |
3269 | old_xmlplus=lp:~launchpad/dtdparser/trunk/ |
3270 | lsprof=lp:~launchpad/lsprof/trunk/ |
3271 | |
3272 | === modified file 'versions.cfg' |
3273 | --- versions.cfg 2009-08-12 12:35:51 +0000 |
3274 | +++ versions.cfg 2009-08-14 18:08:23 +0000 |
3275 | @@ -2,17 +2,20 @@ |
3276 | versions = versions |
3277 | |
3278 | [versions] |
3279 | -# Alphabetical, please! :-) |
3280 | +# Alphabetical, case-insensitive, please! :-) |
3281 | bzr = 1.17 |
3282 | chameleon.core = 1.0b35 |
3283 | chameleon.zpt = 1.0b17 |
3284 | +ClientForm = 0.2.10 |
3285 | # Required by Windmill to run on 2.4 |
3286 | ctypes = 1.0.2 |
3287 | docutils = 0.5 |
3288 | elementtree = 1.2.6-20050316 |
3289 | -# We use a version of feedvalidator that has been changed to not |
3290 | -# change the default socket timeout on import. |
3291 | -feedvalidator = 0.0.0DEV-r1049-hacked |
3292 | +feedvalidator = 0.0.0DEV-r1049 |
3293 | +# We could use a locally hacked version of feedvalidator that has been changed |
3294 | +# to not change the default socket timeout on import. We are currently handling |
3295 | +# that problem elsewhere. |
3296 | +# feedvalidator = 0.0.0DEV-r1049-hacked |
3297 | functest = 0.8.7 |
3298 | funkload = 1.10.0 |
3299 | httplib2 = 0.4.0 |
3300 | @@ -20,6 +23,7 @@ |
3301 | launchpadlib = 1.0.2 |
3302 | lazr.smtptest = 1.1 |
3303 | lazr.uri = 1.0.1 |
3304 | +mechanize = 0.1.7b |
3305 | mocker = 0.10.1 |
3306 | mozrunner = 1.3.4 |
3307 | oauth = 1.0 |
3308 | @@ -27,12 +31,14 @@ |
3309 | PasteDeploy = 1.3.3 |
3310 | python-openid = 2.2.1 |
3311 | pytz = 2009j |
3312 | +RestrictedPython = 3.4.2 |
3313 | setuptools = 0.6c9 |
3314 | simplejson = 2.0.9 |
3315 | simplesettings = 0.4 |
3316 | SimpleTal = 4.1 |
3317 | sourcecodegen = 0.6.9 |
3318 | storm = 0.15 |
3319 | +transaction = 1.0a1 |
3320 | uuid = 1.30 |
3321 | wadllib = 0.1 |
3322 | webunit = 1.3.8 |
3323 | @@ -48,27 +54,90 @@ |
3324 | zc.buildout = 1.4.0dev-gary-r102684 |
3325 | zc.lockfile = 1.0.0 |
3326 | zc.recipe.egg = 1.3.0dev-gary-r102684 |
3327 | -zc.recipe.testrunner = 1.1.0 |
3328 | +zc.zservertracelog = 1.1.5 |
3329 | ZConfig = 2.6.1 |
3330 | +zdaemon = 2.0.2 |
3331 | +ZODB3 = 3.8.1 |
3332 | +zodbcode = 3.4.0 |
3333 | +zope.annotation = 3.4.1 |
3334 | +zope.app.applicationcontrol = 3.4.3 |
3335 | +zope.app.appsetup = 3.4.1 |
3336 | +zope.app.authentication = 3.4.4 |
3337 | +zope.app.basicskin = 3.4.0 |
3338 | +zope.app.broken = 3.4.0 |
3339 | +zope.app.component = 3.4.1 |
3340 | +zope.app.container = 3.5.6 |
3341 | +zope.app.content = 3.4.0 |
3342 | +zope.app.dav = 3.4.1 |
3343 | +zope.app.debug = 3.4.1 |
3344 | +zope.app.dependable = 3.4.0 |
3345 | +zope.app.error = 3.5.1 |
3346 | +zope.app.exception = 3.4.1 |
3347 | +zope.app.file = 3.4.4 |
3348 | +zope.app.folder = 3.4.0 |
3349 | +zope.app.form = 3.4.1 |
3350 | +zope.app.generations = 3.4.1 |
3351 | +zope.app.http = 3.4.1 |
3352 | +zope.app.i18n = 3.4.4 |
3353 | +zope.app.interface = 3.4.0 |
3354 | zope.app.locales = 3.5.1 |
3355 | +zope.app.pagetemplate = 3.4.1 |
3356 | +zope.app.pluggableauth = 3.4.0 |
3357 | +zope.app.principalannotation = 3.4.0 |
3358 | +zope.app.publication = 3.4.4 |
3359 | +zope.app.publisher = 3.4.1 |
3360 | +zope.app.renderer = 3.4.0 |
3361 | +zope.app.rotterdam = 3.4.1 |
3362 | +zope.app.schema = 3.4.0 |
3363 | +zope.app.security = 3.5.2 |
3364 | +zope.app.securitypolicy = 3.4.6 |
3365 | +zope.app.server = 3.4.2 |
3366 | +zope.app.session = 3.5.1 |
3367 | +zope.app.testing = 3.4.3 |
3368 | +zope.app.wsgi = 3.4.1 |
3369 | +zope.app.zapi = 3.4.0 |
3370 | +zope.app.zcmlfiles = 3.4.3 |
3371 | +zope.app.zopeappgenerations = 3.4.0 |
3372 | +zope.cachedescriptors = 3.4.1 |
3373 | zope.component = 3.5.1 |
3374 | -zope.configuration = 3.6.0 |
3375 | +zope.configuration = 3.5.0 |
3376 | zope.contentprovider = 3.5.0 |
3377 | +zope.contenttype = 3.4.0 |
3378 | +zope.copypastemove = 3.4.0 |
3379 | +zope.datetime = 3.4.0 |
3380 | zope.deferredimport = 3.4.0 |
3381 | zope.deprecation = 3.4.0 |
3382 | zope.dottedname = 3.4.5 |
3383 | +zope.dublincore = 3.4.0 |
3384 | +zope.error = 3.5.1 |
3385 | zope.event = 3.4.1 |
3386 | zope.exceptions = 3.5.2 |
3387 | +zope.filerepresentation = 3.4.0 |
3388 | +zope.formlib = 3.4.0 |
3389 | zope.hookable = 3.4.0 |
3390 | zope.i18n = 3.6.0 |
3391 | zope.i18nmessageid = 3.4.3 |
3392 | zope.interface = 3.5.1 |
3393 | +zope.lifecycleevent = 3.4.0 |
3394 | zope.location = 3.5.2 |
3395 | +zope.minmax = 1.1.0 |
3396 | +zope.modulealias = 3.4.0 |
3397 | +zope.pagetemplate = 3.4.0 |
3398 | zope.proxy = 3.5.0 |
3399 | zope.publisher = 3.5.6 |
3400 | zope.schema = 3.5.4 |
3401 | -zope.security = 3.6.0 |
3402 | -zope.tal = 3.4.0 |
3403 | +zope.security = 3.7.1 |
3404 | +zope.securitypolicy = 3.4.1 |
3405 | +zope.sendmail = 3.4.0 |
3406 | +zope.server = 3.4.3 |
3407 | +zope.session = 3.4.1 |
3408 | +zope.size = 3.4.0 |
3409 | +zope.structuredtext = 3.4.0 |
3410 | +zope.tal = 3.4.1 |
3411 | zope.tales = 3.4.0 |
3412 | -zope.testing = 3.7.4 |
3413 | -zope.traversing = 3.5.2 |
3414 | +zope.testbrowser = 3.4.2 |
3415 | +zope.testing = 3.8.1 |
3416 | +zope.thread = 3.4 |
3417 | +# zope.traversing = 3.5.2 |
3418 | +zope.traversing = 3.4.1 |
3419 | +zope.viewlet = 3.4.2 |
This branch changes us to use source distributions for our zope-related
dependencies.
Because we still are using some packages in sourcecode that want to be -particularly Twisted--we filter out pkg_resources
egg-based distributions-
warning in _pythonpath and other scripts. This prevents some test failures
that do not want to see any output from running a command.
There are many other changes, of course.
- Many are driven by changes in reprs of various objects--validation errors idationError) and ClientForm response wrappers seek_wrapper) in particular.
(LaunchpadVal
(httperror_
- Others are for API changes, like in zope.testing canonical/ testing/ __init_ _.py and ).
(lib/
- I commented out the retry tests, as we have discussed.
- Some tests expected zope files to be in the tree, so I had to switch to the
pkg_resources API, or simply use more proper zcml in some cases.
- There's a case or two of tokens needing to be converted from unicode to
binary strings before they go into the URL, as with the
lp:~gary/canonical-identity-provider/zbuildout branch that accompanies this
one.
- zope.schema set fields no longer support sets.Set, only the built-in set,
which also resulted in some changes.
- The transaction.begin API now does not expect to encounter an in-progress launchpad/ doc/storm. txt and /launchpad/ webapp/ ftests/ test_adapter_ permissions. txt).
transaction (lib/canonical/
lib/canonical
- I found a couple of tests that failed in isolation. Related changes are in /launchpad/ doc/batch_ navigation. txt and /launchpad/ scripts/ ftests/ test_oops_ prune.py .
lib/canonical
lib/canonical
- I'm not entirely sure how translations/ stories/ standalone/ xx-pofile- translate- html-tags- escape. txt
lib/lp/
ever passed before. The doctest syntax there was wrong.
- I switched back to the feedvalidator solution that we had discussed way back
when, rather than using the hacked version. I left a comment to describe
the situation.
- Some tests did a browser reload. That now has a different behavior,
resubmitting forms and so on, so I reload the same URL instead.
- I did a fly-by on lib/lp/ soyuz/browser/ tests/binarypac kagerelease- views.txt
because that was a [testfix] problem I diagnosed yesterday, and using
queryMultiAdapter hid the problem.
versions.cfg comments out version numbers only when my changes represent a
*previous* version that what was specified before. Happy to remove those as
well.
For this branch, I made changes and releases in the following packages:
- zope.testing (modified trunk, released and used as zope.testing 3.8.1) publication (modified trunk, eventually to be 3.8.2; also modified 3.4.3, released and used as zope.app. publication 3.4.4)
- zope.security (modified trunk, released and used as zope.security 3.7.1)
- zope.app.
Diffs to the dependencies are below. For zope.testing and zope.security, I
only show the commit that made the substantive changes, rather than the commits
generated by the release process. zope.testing has the biggest changes from
our branch because it significantly changed how it handled subprocesses from
the version we were using in order to support being able to run layers in
...