launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #24634
[Merge] ~cjwatson/launchpad:app-future-imports-prepare into launchpad:master
Colin Watson has proposed merging ~cjwatson/launchpad:app-future-imports-prepare into launchpad:master.
Commit message:
Prepare for __future__ imports in lp.app doctests
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/383046
These are various non-mechanical fixes in preparation for converting the doctests under lp.app to Launchpad's preferred __future__ imports. Most of these are to avoid problems with unicode_literals; the fix is normally either to use print() rather than testing a value's __repr__, or to use six.ensure_str to cause input data to be str rather than unicode where appropriate.
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:app-future-imports-prepare into launchpad:master.
diff --git a/lib/lp/app/browser/doc/launchpad-search-pages.txt b/lib/lp/app/browser/doc/launchpad-search-pages.txt
index 8edcf03..49442e7 100644
--- a/lib/lp/app/browser/doc/launchpad-search-pages.txt
+++ b/lib/lp/app/browser/doc/launchpad-search-pages.txt
@@ -32,12 +32,17 @@ when there is no search text.
When text is not None, the title indicates what was searched.
+ >>> from lp.services.encoding import wsgi_native_string
+
>>> def getSearchView(form):
... search_param_list = []
... for name in sorted(form):
... value = form[name]
- ... search_param_list.append('%s=%s' % (name, value))
- ... query_string = '&'.join(search_param_list)
+ ... if isinstance(value, six.text_type):
+ ... value = wsgi_native_string(value)
+ ... search_param_list.append(b'%s=%s' % (
+ ... wsgi_native_string(name), value))
+ ... query_string = b'&'.join(search_param_list)
... request = LaunchpadTestRequest(
... SERVER_URL='https://launchpad.test/+search',
... QUERY_STRING=query_string, form=form, PATH_INFO='/+search')
@@ -540,7 +545,7 @@ error. Also disable warnings, since we are tossing around malformed Unicode.
>>> with warnings.catch_warnings():
... warnings.simplefilter('ignore')
... search_view = getSearchView(
- ... form={'field.text': '\xfe\xfckr\xfc'})
+ ... form={'field.text': b'\xfe\xfckr\xfc'})
>>> html = search_view()
>>> 'Can not convert your search term' in html
True
diff --git a/lib/lp/app/doc/displaying-numbers.txt b/lib/lp/app/doc/displaying-numbers.txt
index bc89a9f..fcae7bc 100644
--- a/lib/lp/app/doc/displaying-numbers.txt
+++ b/lib/lp/app/doc/displaying-numbers.txt
@@ -45,13 +45,13 @@ to how the Python "%f" string formatter works:
For instance:
>>> foo = 12345.67890
- >>> test_tales('foo/fmt:float/7.2', foo=foo)
- '12345.68'
+ >>> print(test_tales('foo/fmt:float/7.2', foo=foo))
+ 12345.68
Is the same as:
- >>> "%7.2f" % foo
- '12345.68'
+ >>> print("%7.2f" % foo)
+ 12345.68
Here's a set of exhaustive examples:
diff --git a/lib/lp/app/doc/displaying-paragraphs-of-text.txt b/lib/lp/app/doc/displaying-paragraphs-of-text.txt
index a2df0b4..1c48b85 100644
--- a/lib/lp/app/doc/displaying-paragraphs-of-text.txt
+++ b/lib/lp/app/doc/displaying-paragraphs-of-text.txt
@@ -485,7 +485,7 @@ we want to replace a variable number of spaces with the same number of
>>> from lp.app.browser.stringformatter import FormattersAPI
>>> import re
- >>> matchobj = re.match('foo(.*)bar', 'fooX Ybar')
+ >>> matchobj = re.match('foo(.*)bar', six.ensure_str('fooX Ybar'))
>>> matchobj.groups()
('X Y',)
>>> FormattersAPI._substitute_matchgroup_for_spaces(matchobj)
@@ -499,9 +499,10 @@ First, let's try a match of nothing it understands. This is a bug, so we get
an AssertionError.
>>> matchobj = re.match(
- ... ('(?P<bug>xxx)?(?P<faq>www)?(?P<url>yyy)?(?P<oops>zzz)?'
- ... '(?P<lpbranchurl>www)?(?P<clbug>vvv)?'),
- ... 'fish')
+ ... six.ensure_str(
+ ... '(?P<bug>xxx)?(?P<faq>www)?(?P<url>yyy)?(?P<oops>zzz)?'
+ ... '(?P<lpbranchurl>www)?(?P<clbug>vvv)?'),
+ ... six.ensure_str('fish'))
>>> sorted(matchobj.groupdict().items())
[('bug', None),
('clbug', None),
@@ -517,7 +518,9 @@ an AssertionError.
When we have a URL, the URL is made into a link. A quote is added to the
url to demonstrate quoting in the HTML attribute.
- >>> matchobj = re.match('(?P<bug>xxx)?(?P<url>y"y)?', 'y"y')
+ >>> matchobj = re.match(
+ ... six.ensure_str('(?P<bug>xxx)?(?P<url>y"y)?'),
+ ... six.ensure_str('y"y'))
>>> sorted(matchobj.groupdict().items())
[('bug', None), ('url', 'y"y')]
>>> FormattersAPI._linkify_substitution(matchobj)
@@ -527,7 +530,8 @@ When we have a bug reference, the 'bug' group is used as the text of the link,
and the 'bugnum' is used to look up the bug.
>>> matchobj = re.match(
- ... '(?P<bug>xxxx)?(?P<bugnum>2)?(?P<url>yyy)?', 'xxxx2')
+ ... six.ensure_str('(?P<bug>xxxx)?(?P<bugnum>2)?(?P<url>yyy)?'),
+ ... six.ensure_str('xxxx2'))
>>> sorted(matchobj.groupdict().items())
[('bug', 'xxxx'), ('bugnum', '2'), ('url', None)]
>>> FormattersAPI._linkify_substitution(matchobj)
@@ -537,7 +541,8 @@ When the bugnum doesn't match any bug, we still get a link, but get a message
in the link's title.
>>> matchobj = re.match(
- ... '(?P<bug>xxxx)?(?P<bugnum>2000)?(?P<url>yyy)?', 'xxxx2000')
+ ... six.ensure_str('(?P<bug>xxxx)?(?P<bugnum>2000)?(?P<url>yyy)?'),
+ ... six.ensure_str('xxxx2000'))
>>> sorted(matchobj.groupdict().items())
[('bug', 'xxxx'), ('bugnum', '2000'), ('url', None)]
>>> FormattersAPI._linkify_substitution(matchobj)
diff --git a/lib/lp/app/doc/launchpadform.txt b/lib/lp/app/doc/launchpadform.txt
index 6af879c..95bca7e 100644
--- a/lib/lp/app/doc/launchpadform.txt
+++ b/lib/lp/app/doc/launchpadform.txt
@@ -221,7 +221,7 @@ setFieldError() method (for errors specific to a field):
... self.addError('your password may not be the same '
... 'as your name')
... if data.get('password') == 'password':
- ... self.setFieldError('password',
+ ... self.setFieldError(six.ensure_str('password'),
... 'your password must not be "password"')
>>> context = FormTest()
diff --git a/lib/lp/app/doc/launchpadview.txt b/lib/lp/app/doc/launchpadview.txt
index b5617b8..07942aa 100644
--- a/lib/lp/app/doc/launchpadview.txt
+++ b/lib/lp/app/doc/launchpadview.txt
@@ -62,7 +62,7 @@ an IStructuredString implementation.
>>> print view.info_message
None
- >>> view.error_message = 'A simple string.'
+ >>> view.error_message = six.ensure_str('A simple string.')
Traceback (most recent call last):
...
ValueError: <type 'str'> is not a valid value for error_message,
@@ -70,7 +70,7 @@ an IStructuredString implementation.
>>> print view.error_message
None
- >>> view.info_message = 'A simple string.'
+ >>> view.info_message = six.ensure_str('A simple string.')
Traceback (most recent call last):
...
ValueError: <type 'str'> is not a valid value for info_message,
diff --git a/lib/lp/app/doc/loginstatus-pages.txt b/lib/lp/app/doc/loginstatus-pages.txt
index 16fceaf..a07e314 100644
--- a/lib/lp/app/doc/loginstatus-pages.txt
+++ b/lib/lp/app/doc/loginstatus-pages.txt
@@ -27,8 +27,8 @@ Generic request without query args.
False
>>> status.login_shown
True
- >>> status.login_url
- 'http://localhost/foo/bar/+login'
+ >>> print(status.login_url)
+ http://localhost/foo/bar/+login
Virtual hosted request with a trailing slash.
@@ -37,8 +37,8 @@ Virtual hosted request with a trailing slash.
... '/++vh++https:staging.example.com:433/++/foo/bar/', '')
>>> context = object()
>>> status = LoginStatus(context, request)
- >>> status.login_url
- 'https://staging.example.com/foo/bar/+login'
+ >>> print(status.login_url)
+ https://staging.example.com/foo/bar/+login
Virtual hosted request with no trailing slash.
@@ -47,8 +47,8 @@ Virtual hosted request with no trailing slash.
... '/++vh++https:staging.example.com:433/++/foo/bar', '')
>>> context = object()
>>> status = LoginStatus(context, request)
- >>> status.login_url
- 'https://staging.example.com/foo/bar/+login'
+ >>> print(status.login_url)
+ https://staging.example.com/foo/bar/+login
Generic request with trailing slash and query parameters.
@@ -56,8 +56,8 @@ Generic request with trailing slash and query parameters.
... 'http://localhost', '/foo/bar/', 'x=1&y=2')
>>> context = object()
>>> status = LoginStatus(context, request)
- >>> status.login_url
- 'http://localhost/foo/bar/+login?x=1&y=2'
+ >>> print(status.login_url)
+ http://localhost/foo/bar/+login?x=1&y=2
The login page.
@@ -80,8 +80,8 @@ The logout page.
False
>>> status.login_shown
True
- >>> status.login_url
- 'http://localhost/+login'
+ >>> print(status.login_url)
+ http://localhost/+login
The +openid-callback page.
@@ -93,8 +93,8 @@ The +openid-callback page.
False
>>> status.login_shown
True
- >>> status.login_url
- 'http://localhost/+login'
+ >>> print(status.login_url)
+ http://localhost/+login
Logging in.
diff --git a/lib/lp/app/doc/menus.txt b/lib/lp/app/doc/menus.txt
index e982b25..e761f1b 100644
--- a/lib/lp/app/doc/menus.txt
+++ b/lib/lp/app/doc/menus.txt
@@ -33,7 +33,7 @@ later, implementations having facets and menus will be defined.
>>> import sys
>>> import types
- >>> cookingexample = types.ModuleType('cookingexample')
+ >>> cookingexample = types.ModuleType(six.ensure_str('cookingexample'))
>>> sys.modules['lp.app.cookingexample'] = cookingexample
>>> cookingexample.ICookbook = ICookbook
diff --git a/lib/lp/app/doc/tales.txt b/lib/lp/app/doc/tales.txt
index cc7606e..682360a 100644
--- a/lib/lp/app/doc/tales.txt
+++ b/lib/lp/app/doc/tales.txt
@@ -266,8 +266,8 @@ fmt:rfc822utcdatetime.
To truncate a long string, use fmt:shorten:
- >>> test_tales('foo/fmt:shorten/8', foo='abcdefghij')
- 'abcde...'
+ >>> print(test_tales('foo/fmt:shorten/8', foo='abcdefghij'))
+ abcde...
To ellipsize the middle of a string. use fmt:ellipsize and pass the max
length.
@@ -1080,35 +1080,35 @@ the start of the string is not a letter. If any invalid characters are
stripped out, to ensure the id is unique, a base64 encoding is appended to the
id.
- >>> test_tales('foo/fmt:css-id', foo='beta2-milestone')
- 'beta2-milestone'
+ >>> print(test_tales('foo/fmt:css-id', foo='beta2-milestone'))
+ beta2-milestone
- >>> test_tales('foo/fmt:css-id', foo='user name')
- 'user-name-dXNlciBuYW1l'
+ >>> print(test_tales('foo/fmt:css-id', foo='user name'))
+ user-name-dXNlciBuYW1l
- >>> test_tales('foo/fmt:css-id', foo='1.0.1_series')
- 'j1-0-1_series'
+ >>> print(test_tales('foo/fmt:css-id', foo='1.0.1_series'))
+ j1-0-1_series
An optional prefix for the if can be added to the path. It too will be
escaped.
- >>> test_tales('foo/fmt:css-id/series-', foo='1.0.1_series')
- 'series-1-0-1_series'
+ >>> print(test_tales('foo/fmt:css-id/series-', foo='1.0.1_series'))
+ series-1-0-1_series
- >>> test_tales('foo/fmt:css-id/series_', foo='1.0.1_series')
- 'series_1-0-1_series'
+ >>> print(test_tales('foo/fmt:css-id/series_', foo='1.0.1_series'))
+ series_1-0-1_series
- >>> test_tales('foo/fmt:css-id/0series-', foo='1.0.1_series')
- 'j0series-1-0-1_series'
+ >>> print(test_tales('foo/fmt:css-id/0series-', foo='1.0.1_series'))
+ j0series-1-0-1_series
Zope fields are rendered with a period, and we need to ensure there is a way
to retain the periods in the css id even though we would prefer not to.
- >>> test_tales('foo/fmt:zope-css-id', foo='field.bug.target')
- 'field.bug.target'
+ >>> print(test_tales('foo/fmt:zope-css-id', foo='field.bug.target'))
+ field.bug.target
- >>> test_tales('foo/fmt:zope-css-id', foo='field.gtk+_package')
- 'field.gtk-_package-ZmllbGQuZ3RrK19wYWNrYWdl'
+ >>> print(test_tales('foo/fmt:zope-css-id', foo='field.gtk+_package'))
+ field.gtk-_package-ZmllbGQuZ3RrK19wYWNrYWdl
The fmt: namespace to get strings (obfuscation)
-----------------------------------------------
@@ -1119,32 +1119,36 @@ unauthenticated users, the email address can be hidden. The address is
replaced with the message '<email address hidden>'.
>>> login(ANONYMOUS)
- >>> test_tales('foo/fmt:obfuscate-email', foo='name.surname@xxxxxxxxxxx')
- '<email address hidden>'
+ >>> print(test_tales(
+ ... 'foo/fmt:obfuscate-email', foo='name.surname@xxxxxxxxxxx'))
+ <email address hidden>
- >>> test_tales('foo/fmt:obfuscate-email', foo='name@xxxxxxxxxxxxxxxxxxx')
- '<email address hidden>'
+ >>> print(test_tales(
+ ... 'foo/fmt:obfuscate-email', foo='name@xxxxxxxxxxxxxxxxxxx'))
+ <email address hidden>
- >>> test_tales('foo/fmt:obfuscate-email', foo='name+sub@xxxxxxxxxx')
- '<email address hidden>'
+ >>> print(test_tales(
+ ... 'foo/fmt:obfuscate-email', foo='name+sub@xxxxxxxxxx'))
+ <email address hidden>
- >>> test_tales('foo/fmt:obfuscate-email',
- ... foo='long_name@xxxxxxxxxxxxxxxxxxxxxxxx')
- '<email address hidden>'
+ >>> print(test_tales('foo/fmt:obfuscate-email',
+ ... foo='long_name@xxxxxxxxxxxxxxxxxxxxxxxx'))
+ <email address hidden>
- >>> test_tales('foo/fmt:obfuscate-email',
- ... foo='"long/name="@organization.org')
- '"<email address hidden>'
+ >>> print(test_tales('foo/fmt:obfuscate-email',
+ ... foo='"long/name="@organization.org'))
+ "<email address hidden>
- >>> test_tales('foo/fmt:obfuscate-email',
- ... foo='long-name@building.museum')
- '<email address hidden>'
+ >>> print(test_tales('foo/fmt:obfuscate-email',
+ ... foo='long-name@building.museum'))
+ <email address hidden>
- >>> test_tales('foo/fmt:obfuscate-email', foo='foo@xxxxxxxxxxxxxxxx')
- '<email address hidden>'
+ >>> print(test_tales(
+ ... 'foo/fmt:obfuscate-email', foo='foo@xxxxxxxxxxxxxxxx'))
+ <email address hidden>
- >>> test_tales('foo/fmt:obfuscate-email', foo='<foo@xxxxxxx>')
- '<email address hidden>'
+ >>> print(test_tales('foo/fmt:obfuscate-email', foo='<foo@xxxxxxx>'))
+ <email address hidden>
>>> print test_tales('foo/fmt:obfuscate-email/fmt:text-to-html',
... foo=signature)
@@ -1153,41 +1157,43 @@ replaced with the message '<email address hidden>'.
<email address hidden><br />
Guilty of stealing everything I am.</p>
- >>> test_tales('foo/fmt:obfuscate-email',
- ... foo='mailto:long-name@xxxxxxxxxxxxxxxx')
- 'mailto:<email address hidden>'
+ >>> print(test_tales('foo/fmt:obfuscate-email',
+ ... foo='mailto:long-name@xxxxxxxxxxxxxxxx'))
+ mailto:<email address hidden>
- >>> test_tales('foo/fmt:obfuscate-email',
- ... foo='http://person:password@xxxxxxxx')
- 'http://person:<email address hidden>'
+ >>> print(test_tales('foo/fmt:obfuscate-email',
+ ... foo='http://person:password@xxxxxxxx'))
+ http://person:<email address hidden>
- >>> test_tales('foo/fmt:obfuscate-email', foo='name @ host.school.edu')
- 'name @ host.school.edu'
+ >>> print(test_tales(
+ ... 'foo/fmt:obfuscate-email', foo='name @ host.school.edu'))
+ name @ host.school.edu
- >>> test_tales('foo/fmt:obfuscate-email', foo='person@host')
- 'person@host'
+ >>> print(test_tales('foo/fmt:obfuscate-email', foo='person@host'))
+ person@host
- >>> test_tales('foo/fmt:obfuscate-email', foo='(head, tail)=@array')
- '(head, tail)=@array'
+ >>> print(test_tales(
+ ... 'foo/fmt:obfuscate-email', foo='(head, tail)=@array'))
+ (head, tail)=@array
- >>> test_tales('foo/fmt:obfuscate-email', foo='@staticmethod')
- '@staticmethod'
+ >>> print(test_tales('foo/fmt:obfuscate-email', foo='@staticmethod'))
+ @staticmethod
- >>> test_tales('foo/fmt:obfuscate-email', foo='element/@attribute')
- 'element/@attribute'
+ >>> print(test_tales('foo/fmt:obfuscate-email', foo='element/@attribute'))
+ element/@attribute
>>> bad_address = (
... "medicalwei@sara:~$ Spinning................................"
... "...........................................................not")
- >>> test_tales('foo/fmt:obfuscate-email', foo=bad_address)
- 'medicalwei@sara:~$ ...'
+ >>> print(test_tales('foo/fmt:obfuscate-email', foo=bad_address))
+ medicalwei@sara:~$ ...
However, if the user is authenticated, the email address is not
obfuscated.
>>> login('no-priv@xxxxxxxxxxxxx')
- >>> test_tales('foo/fmt:obfuscate-email', foo='user@xxxxxxxx')
- 'user@xxxxxxxx'
+ >>> print(test_tales('foo/fmt:obfuscate-email', foo='user@xxxxxxxx'))
+ user@xxxxxxxx
Linkification of email addresses
@@ -1220,8 +1226,8 @@ Team addresses are linkified with a team icon:
Unknown email addresses are not altered in any way:
- >>> test_tales('foo/fmt:linkify-email', foo='nobody@xxxxxxxxxxx')
- 'nobody@xxxxxxxxxxx'
+ >>> print(test_tales('foo/fmt:linkify-email', foo='nobody@xxxxxxxxxxx'))
+ nobody@xxxxxxxxxxx
Users who specify that their email addresses must be hidden also do not
get linkified. test@xxxxxxxxxxxxx is hidden:
@@ -1231,8 +1237,8 @@ get linkified. test@xxxxxxxxxxxxx is hidden:
>>> discreet_user.hide_email_addresses
True
- >>> test_tales('foo/fmt:linkify-email', foo='test@xxxxxxxxxxxxx')
- 'test@xxxxxxxxxxxxx'
+ >>> print(test_tales('foo/fmt:linkify-email', foo='test@xxxxxxxxxxxxx'))
+ test@xxxxxxxxxxxxx
Test the 'fmt:' namespace where the context is a dict.
diff --git a/lib/lp/app/doc/textformatting.txt b/lib/lp/app/doc/textformatting.txt
index cda72a0..3d15a5b 100644
--- a/lib/lp/app/doc/textformatting.txt
+++ b/lib/lp/app/doc/textformatting.txt
@@ -230,14 +230,14 @@ The line endings are normalized to \n, so if we get a text with
dos-style line endings, we get the following result:
>>> mailwrapper = MailWrapper(width=56)
- >>> dos_style_comment = (
+ >>> dos_style_comment = six.ensure_str(
... "This paragraph is longer than 56 characters, so it should"
... " be wrapped even though the paragraphs are separated with"
... " dos-style line endings."
... "\r\n\r\n"
... "Here's the second paragraph.")
>>> wrapped_text = mailwrapper.format(dos_style_comment)
- >>> wrapped_text.split('\n')
+ >>> wrapped_text.split(six.ensure_str('\n'))
['This paragraph is longer than 56 characters, so it',
'should be wrapped even though the paragraphs are',
'separated with dos-style line endings.',
diff --git a/lib/lp/app/tests/test_doc.py b/lib/lp/app/tests/test_doc.py
index 495499b..3e93aee 100644
--- a/lib/lp/app/tests/test_doc.py
+++ b/lib/lp/app/tests/test_doc.py
@@ -16,6 +16,7 @@ from lp.testing.pages import (
)
from lp.testing.systemdocs import (
LayeredDocFileSuite,
+ setGlobs,
setUp,
tearDown,
)
@@ -42,7 +43,7 @@ special = {
layer=LaunchpadFunctionalLayer,
),
'menus.txt': LayeredDocFileSuite(
- '../doc/menus.txt', layer=None,
+ '../doc/menus.txt', setUp=setGlobs, layer=None,
),
'stories/launchpad-search(Bing)': PageTestSuite(
'../stories/launchpad-search/',
diff --git a/lib/lp/app/validators/name.py b/lib/lp/app/validators/name.py
index 307795b..5b2575f 100644
--- a/lib/lp/app/validators/name.py
+++ b/lib/lp/app/validators/name.py
@@ -28,10 +28,10 @@ def sanitize_name(name):
The characters not allowed in Launchpad names are described by
invalid_name_pattern.
- >>> sanitize_name('foo_bar')
- 'foobar'
- >>> sanitize_name('baz bar $fd')
- 'bazbarfd'
+ >>> print(sanitize_name('foo_bar'))
+ foobar
+ >>> print(sanitize_name('baz bar $fd'))
+ bazbarfd
"""
return invalid_name_pattern.sub('', name)
diff --git a/lib/lp/app/validators/username.py b/lib/lp/app/validators/username.py
index cce4d4b..acfe874 100644
--- a/lib/lp/app/validators/username.py
+++ b/lib/lp/app/validators/username.py
@@ -27,12 +27,12 @@ def sanitize_username(username):
The characters not allowed in Launchpad usernames are described by
`username_invalid_pattern`.
- >>> sanitize_username('foo_bar')
- 'foobar'
- >>> sanitize_username('foo.bar+baz')
- 'foobarbaz'
- >>> sanitize_username('-#foo -$fd?.0+-')
- 'foo-fd0'
+ >>> print(sanitize_username('foo_bar'))
+ foobar
+ >>> print(sanitize_username('foo.bar+baz'))
+ foobarbaz
+ >>> print(sanitize_username('-#foo -$fd?.0+-'))
+ foo-fd0
"""
return username_invalid_pattern.sub('', username)
diff --git a/lib/lp/app/widgets/doc/announcement-date-widget.txt b/lib/lp/app/widgets/doc/announcement-date-widget.txt
index becbaad..d65b4f2 100644
--- a/lib/lp/app/widgets/doc/announcement-date-widget.txt
+++ b/lib/lp/app/widgets/doc/announcement-date-widget.txt
@@ -8,7 +8,7 @@ future, or to manually publish it later.
>>> from lp.testing.pages import extract_text
>>> from lp.services.webapp.servers import LaunchpadTestRequest
>>> from lp.app.widgets.announcementdate import AnnouncementDateWidget
- >>> field = Field(__name__='foo', title=u'Foo')
+ >>> field = Field(__name__=six.ensure_str('foo'), title=u'Foo')
>>> widget = AnnouncementDateWidget(field, LaunchpadTestRequest())
>>> print extract_text(widget())
Publish this announcement:
diff --git a/lib/lp/app/widgets/doc/project-scope-widget.txt b/lib/lp/app/widgets/doc/project-scope-widget.txt
index e497797..0a87803 100644
--- a/lib/lp/app/widgets/doc/project-scope-widget.txt
+++ b/lib/lp/app/widgets/doc/project-scope-widget.txt
@@ -14,7 +14,8 @@ selected.
>>> empty_request = LaunchpadTestRequest()
>>> scope_field = Choice(
- ... __name__='scope', vocabulary='ProjectGroup', required=False)
+ ... __name__=six.ensure_str('scope'), vocabulary='ProjectGroup',
+ ... required=False)
>>> scope_field = scope_field.bind(object())
>>> widget = ProjectScopeWidget(
... scope_field, scope_field.vocabulary, empty_request)
diff --git a/lib/lp/app/widgets/doc/stripped-text-widget.txt b/lib/lp/app/widgets/doc/stripped-text-widget.txt
index 26f3b06..fe9ed47 100644
--- a/lib/lp/app/widgets/doc/stripped-text-widget.txt
+++ b/lib/lp/app/widgets/doc/stripped-text-widget.txt
@@ -15,8 +15,8 @@ set value.
>>> thing = Thing('abc')
>>> non_required_field.set(thing, ' egf ')
- >>> non_required_field.get(thing)
- 'egf'
+ >>> print(non_required_field.get(thing)) # doctest: -NORMALIZE_WHITESPACE
+ egf
None is an accepted field value.
@@ -57,7 +57,7 @@ provided.
True
>>> required_field = StrippedTextLine(
- ... __name__='field', title=u'Title', required=True)
+ ... __name__=six.ensure_str('field'), title=u'Title', required=True)
>>> request = LaunchpadTestRequest(form={'field.field':' \n '})
>>> widget = StrippedTextWidget(required_field, request)
>>> widget.getInputValue()
diff --git a/lib/lp/bugs/stories/bugs/xx-incomplete-bugs.txt b/lib/lp/bugs/stories/bugs/xx-incomplete-bugs.txt
index 7d1aade..48ef775 100644
--- a/lib/lp/bugs/stories/bugs/xx-incomplete-bugs.txt
+++ b/lib/lp/bugs/stories/bugs/xx-incomplete-bugs.txt
@@ -261,8 +261,6 @@ Since no new comments have been added after we changed the status to
Incomplete, we can now find that bug searching for Incomplete (without
response) bugs.
- >>> import six
-
>>> user_browser.open(
... 'http://bugs.launchpad.test/jokosher/+bugs?advanced=1')
>>> user_browser.getControl(name='field.status:list').value = (
diff --git a/lib/lp/registry/stories/teammembership/xx-teammembership.txt b/lib/lp/registry/stories/teammembership/xx-teammembership.txt
index 06208ac..873a275 100644
--- a/lib/lp/registry/stories/teammembership/xx-teammembership.txt
+++ b/lib/lp/registry/stories/teammembership/xx-teammembership.txt
@@ -224,8 +224,6 @@ On a team's +members page we can see all active members of that team, as
well as the former members and the ones which proposed themselves or that
have been invited.
- >>> import six
-
>>> def print_members(contents, type):
... table = find_tag_by_id(contents, type)
... for link in table.findAll('a'):
diff --git a/lib/lp/testing/pages.py b/lib/lp/testing/pages.py
index e552b4b..6fddbc1 100644
--- a/lib/lp/testing/pages.py
+++ b/lib/lp/testing/pages.py
@@ -936,6 +936,7 @@ def setUpGlobs(test, future=False):
test.globs['print_tag_with_id'] = print_tag_with_id
test.globs['PageTestLayer'] = PageTestLayer
test.globs['stop'] = stop
+ test.globs['six'] = six
if future:
import __future__
diff --git a/lib/lp/testing/systemdocs.py b/lib/lp/testing/systemdocs.py
index d609bc8..3fb72bf 100644
--- a/lib/lp/testing/systemdocs.py
+++ b/lib/lp/testing/systemdocs.py
@@ -24,6 +24,7 @@ import pdb
import pprint
import sys
+import six
import transaction
from zope.component import getUtility
from zope.testing.loggingsupport import Handler
@@ -234,6 +235,7 @@ def setGlobs(test, future=False):
test.globs['launchpadlib_for'] = launchpadlib_for
test.globs['launchpadlib_credentials_for'] = launchpadlib_credentials_for
test.globs['oauth_access_token_for'] = oauth_access_token_for
+ test.globs['six'] = six
if future:
import __future__