launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #26235
[Merge] ~cjwatson/launchpad:py3-services-doctest-unicode-strings into launchpad:master
Colin Watson has proposed merging ~cjwatson/launchpad:py3-services-doctest-unicode-strings into launchpad:master.
Commit message:
lp.services: Fix u'...' doctest examples for Python 3
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/397616
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:py3-services-doctest-unicode-strings into launchpad:master.
diff --git a/lib/lp/services/config/doc/canonical-config.txt b/lib/lp/services/config/doc/canonical-config.txt
index 3b6af93..796fd0b 100644
--- a/lib/lp/services/config/doc/canonical-config.txt
+++ b/lib/lp/services/config/doc/canonical-config.txt
@@ -58,8 +58,8 @@ using persistent helpers - see lp.testing.layers).
>>> config.filename
'.../launchpad-lazr.conf'
- >>> config.extends.filename
- u'.../launchpad-lazr.conf'
+ >>> print(config.extends.filename)
+ /.../launchpad-lazr.conf
LaunchpadConfig provides __contains__ and __getitem__ to check and
access lazr.config sections and keys.
@@ -161,8 +161,8 @@ conf file name that is loaded.
>>> test_config.filename
'.../configs/testrunner/test-process-lazr.conf'
- >>> test_config.extends.filename
- u'.../configs/testrunner/launchpad-lazr.conf'
+ >>> print(test_config.extends.filename)
+ /.../configs/testrunner/launchpad-lazr.conf
>>> test_config.answertracker.days_before_expiration
300
@@ -181,8 +181,8 @@ process's name.
>>> test_config.filename
'.../configs/testrunner/launchpad-lazr.conf'
- >>> test_config.extends.filename
- u'.../configs/development/launchpad-lazr.conf'
+ >>> print(test_config.extends.filename)
+ /.../configs/development/launchpad-lazr.conf
>>> test_config.answertracker.days_before_expiration
15
@@ -222,8 +222,8 @@ argument to the constructor.
# >>> from lp.services.config import config
# >>> config.filename
# '.../configs/mailman-itests/launchpad-lazr.conf'
-# >>> config.extends.filename
-# u'.../configs/development/launchpad-lazr.conf'
+# >>> print(config.extends.filename)
+# /.../configs/development/launchpad-lazr.conf
# >>> config.database.dbname
# 'launchpad_dev'
diff --git a/lib/lp/services/database/doc/decoratedresultset.txt b/lib/lp/services/database/doc/decoratedresultset.txt
index 0066d84..c9857ed 100644
--- a/lib/lp/services/database/doc/decoratedresultset.txt
+++ b/lib/lp/services/database/doc/decoratedresultset.txt
@@ -68,13 +68,13 @@ decorated results:
>>> decorated_result_set.config(return_both=True)
<lp.services.database.decoratedresultset.DecoratedResultSet object at ...>
>>> for dist in decorated_result_set:
- ... print(dist)
- (<Distribution 'Debian' (debian)>, u'Dist name is: debian')
- (<Distribution 'Gentoo' (gentoo)>, u'Dist name is: gentoo')
+ ... print(pretty(dist))
+ (<Distribution 'Debian' (debian)>, 'Dist name is: debian')
+ (<Distribution 'Gentoo' (gentoo)>, 'Dist name is: gentoo')
...
- (<Distribution 'ubuntutest' (ubuntutest)>, u'Dist name is: ubuntutest')
- >>> decorated_result_set.first()
- (<Distribution 'Debian' (debian)>, u'Dist name is: debian')
+ (<Distribution 'ubuntutest' (ubuntutest)>, 'Dist name is: ubuntutest')
+ >>> print(pretty(decorated_result_set.first()))
+ (<Distribution 'Debian' (debian)>, 'Dist name is: debian')
This works even if there are multiple levels:
diff --git a/lib/lp/services/database/doc/storm.txt b/lib/lp/services/database/doc/storm.txt
index 5d83c4e..abe5dc3 100644
--- a/lib/lp/services/database/doc/storm.txt
+++ b/lib/lp/services/database/doc/storm.txt
@@ -91,8 +91,8 @@ similarly wrapped.
>>> person = getUtility(IPersonSet).getByEmail('no-priv@xxxxxxxxxxxxx')
>>> removeSecurityProxy(person) is person
False
- >>> person.displayname
- u'No Privileges Person'
+ >>> print(person.displayname)
+ No Privileges Person
>>> person.name = 'foo'
... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
Traceback (most recent call last):
@@ -102,8 +102,8 @@ similarly wrapped.
>>> person = IMasterObject(person)
>>> removeSecurityProxy(person) is person
False
- >>> person.displayname
- u'No Privileges Person'
+ >>> print(person.displayname)
+ No Privileges Person
>>> person.name = 'foo'
... # doctest: +IGNORE_EXCEPTION_MODULE_IN_PYTHON2
Traceback (most recent call last):
@@ -113,8 +113,8 @@ similarly wrapped.
>>> person = IMasterObject(removeSecurityProxy(person))
>>> removeSecurityProxy(person) is person
True
- >>> person.displayname
- u'No Privileges Person'
+ >>> print(person.displayname)
+ No Privileges Person
>>> person.name = 'foo'
Our objects may compare equal even if they have come from different
diff --git a/lib/lp/services/database/doc/textsearching.txt b/lib/lp/services/database/doc/textsearching.txt
index 8951f1b..77c022f 100644
--- a/lib/lp/services/database/doc/textsearching.txt
+++ b/lib/lp/services/database/doc/textsearching.txt
@@ -651,8 +651,11 @@ by tsearch2. All words are also stemmed.
>>> from lp.services.database.nl_search import nl_term_candidates
- >>> nl_term_candidates('When I start firefox, it crashes')
- [u'start', u'firefox', u'crash']
+ >>> for term in nl_term_candidates('When I start firefox, it crashes'):
+ ... print(term)
+ start
+ firefox
+ crash
It returns an empty list when there is only stop-words in the query:
@@ -661,10 +664,15 @@ It returns an empty list when there is only stop-words in the query:
Except for the hyphenation character, all non-word caracters are ignored:
- >>> nl_term_candidates(
- ... "Will the \'\'|\'\' character (inside a ''quoted'' string) "
- ... "work???")
- [u'charact', u'insid', u'quot', u'string', u'work']
+ >>> for term in nl_term_candidates(
+ ... "Will the \'\'|\'\' character (inside a ''quoted'' string) "
+ ... "work???"):
+ ... print(term)
+ charact
+ insid
+ quot
+ string
+ work
nl_phrase_search()
@@ -700,9 +708,9 @@ More than 50% of the questions matches firefox:
So firefox will be removed from the final query:
- >>> nl_phrase_search('system is slow when running firefox', Question,
- ... fast_enabled=False)
- u'system|slow|run'
+ >>> print(nl_phrase_search('system is slow when running firefox', Question,
+ ... fast_enabled=False))
+ system|slow|run
>>> nl_term_candidates('how do I do this?')
[]
@@ -712,14 +720,14 @@ So firefox will be removed from the final query:
The fast code path does not remove any terms. Rather it uses an & query over
all the terms combined with an & query for each ordinal-1 subset of the terms:
- >>> nl_phrase_search('system is slow when running firefox on ubuntu',
- ... Question)
- u'(firefox&run&slow&system&ubuntu)|(run&slow&system&ubuntu)|(firefox&slow&system&ubuntu)|(firefox&run&system&ubuntu)|(firefox&run&slow&ubuntu)|(firefox&run&slow&system)'
+ >>> print(nl_phrase_search('system is slow when running firefox on ubuntu',
+ ... Question))
+ (firefox&run&slow&system&ubuntu)|(run&slow&system&ubuntu)|(firefox&slow&system&ubuntu)|(firefox&run&system&ubuntu)|(firefox&run&slow&ubuntu)|(firefox&run&slow&system)
Short queries are expanded more simply:
- >>> nl_phrase_search('system is slow', Question)
- u'slow|system'
+ >>> print(nl_phrase_search('system is slow', Question))
+ slow|system
Using other constraints
@@ -743,11 +751,11 @@ considered a stop word by tsearch2).
>>> float(get_questions) / firefox_count > 0.50
True
- >>> nl_phrase_search(
+ >>> print(nl_phrase_search(
... 'firefox gets very slow on flickr', Question,
... [Question.product == firefox_product, Product.active],
- ... fast_enabled=False)
- u'slow|flickr'
+ ... fast_enabled=False))
+ slow|flickr
When the query only has stop words in it, the returned query will be the empty
string:
@@ -760,9 +768,9 @@ is done.
>>> IStore(Question).find(Question, Question.product_id == -1).count()
0
- >>> nl_phrase_search('firefox is very slow on flickr', Question,
- ... [Question.product == -1])
- u'(firefox&flickr&slow)|(flickr&slow)|(firefox&slow)|(firefox&flickr)'
+ >>> print(nl_phrase_search('firefox is very slow on flickr', Question,
+ ... [Question.product == -1]))
+ (firefox&flickr&slow)|(flickr&slow)|(firefox&slow)|(firefox&flickr)
No keywords filtering with few rows
@@ -799,8 +807,8 @@ And more than half of these contain the keyword "firefox" in them:
But the keyword is still keep because there are only less than 5
questions:
- >>> nl_phrase_search(
+ >>> print(nl_phrase_search(
... 'firefox is slow', Question,
... [Question.distribution == ubuntu,
- ... Question.sourcepackagename == firefox_package.sourcepackagename])
- u'firefox|slow'
+ ... Question.sourcepackagename == firefox_package.sourcepackagename]))
+ firefox|slow
diff --git a/lib/lp/services/database/sqlbase.py b/lib/lp/services/database/sqlbase.py
index 3942ba7..57ba46d 100644
--- a/lib/lp/services/database/sqlbase.py
+++ b/lib/lp/services/database/sqlbase.py
@@ -71,6 +71,7 @@ from lp.services.database.interfaces import (
IStoreSelector,
MAIN_STORE,
)
+from lp.services.helpers import backslashreplace
from lp.services.propertycache import clear_property_cache
# Default we want for scripts, and the PostgreSQL default. Note psycopg1 will
@@ -320,8 +321,11 @@ def quote(x):
query will be a Unicode string (the entire query will be encoded
before sending across the wire to the database).
- >>> quote(u"\N{TRADE MARK SIGN}")
- u"E'\u2122'"
+ >>> quoted = quote(u"\N{TRADE MARK SIGN}")
+ >>> isinstance(quoted, six.text_type)
+ True
+ >>> print(backslashreplace(quoted))
+ E'\u2122'
Timezone handling is not implemented, since all timestamps should
be UTC anyway.
diff --git a/lib/lp/services/database/tests/decoratedresultset.txt b/lib/lp/services/database/tests/decoratedresultset.txt
index 30262c4..98706e8 100644
--- a/lib/lp/services/database/tests/decoratedresultset.txt
+++ b/lib/lp/services/database/tests/decoratedresultset.txt
@@ -51,11 +51,11 @@ Make sure that the new result set is actually different:
But it still contains the expected results:
>>> for distro in result_copy:
- ... distro
+ ... print(distro)
7 elements in result set
- u'Dist name is: debian'
+ Dist name is: debian
...
- u'Dist name is: ubuntutest'
+ Dist name is: ubuntutest
== config() ==
@@ -80,8 +80,8 @@ but returns a copy of itself:
The decorated __getitem__ gets the item from the original result set
and decorates the item before returning it:
- >>> decorated_result_set[0]
- u'Dist name is: debian'
+ >>> print(decorated_result_set[0])
+ Dist name is: debian
== any() ==
@@ -98,9 +98,9 @@ and decorates the result:
The decorated first() method calls the original result set's first()
method and decorates the result:
- >>> decorated_result_set.first()
+ >>> print(decorated_result_set.first())
1 elements in result set
- u'Dist name is: debian'
+ Dist name is: debian
pre_iter_hook is not called from methods like first() or one() which return
at most one row:
@@ -115,9 +115,9 @@ at most one row:
The decorated last() method calls the original result set's last()
method and decorates the result:
- >>> decorated_result_set.last()
+ >>> print(decorated_result_set.last())
1 elements in result set
- u'Dist name is: ubuntutest'
+ Dist name is: ubuntutest
== order_by() ==
@@ -128,23 +128,23 @@ method and decorates the result:
>>> ordered_results = decorated_result_set.order_by(
... Desc(Distribution.name))
>>> for dist in ordered_results:
- ... dist
+ ... print(dist)
7 elements in result set
- u'Dist name is: ubuntutest'
+ Dist name is: ubuntutest
...
- u'Dist name is: debian'
+ Dist name is: debian
== one() ==
The decorated one() method calls the original result set's one()
method and decorates the result:
- >>> decorated_result_set.config(offset=2, limit=1).one()
+ >>> print(decorated_result_set.config(offset=2, limit=1).one())
1 elements in result set
- u'Dist name is: redhat'
+ Dist name is: redhat
- >>> result_decorator(decorated_result_set.result_set.one())
- u'Dist name is: redhat'
+ >>> print(result_decorator(decorated_result_set.result_set.one()))
+ Dist name is: redhat
== splicing ==
@@ -165,9 +165,9 @@ a refined query.
>>> ubuntu_distros = removeSecurityProxy(decorated_result_set).find(
... "Distribution.name like 'ubuntu%'")
>>> for dist in ubuntu_distros:
- ... dist
- u'Dist name is: ubuntu'
- u'Dist name is: ubuntutest'
+ ... print(dist)
+ Dist name is: ubuntu
+ Dist name is: ubuntutest
== get_plain_result_set() ==
diff --git a/lib/lp/services/feeds/doc/feeds.txt b/lib/lp/services/feeds/doc/feeds.txt
index b855388..939c302 100644
--- a/lib/lp/services/feeds/doc/feeds.txt
+++ b/lib/lp/services/feeds/doc/feeds.txt
@@ -141,14 +141,14 @@ be escaped using xml entities such as "<".
>>> from lp.services.feeds.feed import FeedTypedData
>>> text = FeedTypedData("<b> and and &")
- >>> text.content
- u'<b> and &nbsp; and &amp;'
+ >>> print(text.content)
+ <b> and &nbsp; and &amp;
>>> text2 = FeedTypedData("<b> and and &", content_type="text")
- >>> text2.content
- u'<b> and &nbsp; and &amp;'
+ >>> print(text2.content)
+ <b> and &nbsp; and &amp;
>>> html = FeedTypedData("<b> and and &", content_type="html")
- >>> html.content
- u'<b> and &nbsp; and &amp;'
+ >>> print(html.content)
+ <b> and &nbsp; and &amp;
Since xhtml is valid xml, the "<" and ">" characters do not need to be
escaped. However, xhtml supports many more entities than xml, and Internet
@@ -160,5 +160,5 @@ we are testing xhtml encoding here in case we need it in the future.
>>> xhtml = FeedTypedData("<b> and and &</b><hr/>",
... content_type="xhtml")
- >>> xhtml.content
- u'<b> and \xa0 and &</b><hr/>'
+ >>> print(backslashreplace(xhtml.content))
+ <b> and \xa0 and &</b><hr/>
diff --git a/lib/lp/services/fields/doc/uri-field.txt b/lib/lp/services/fields/doc/uri-field.txt
index ef9bb3e..f4c9c00 100644
--- a/lib/lp/services/fields/doc/uri-field.txt
+++ b/lib/lp/services/fields/doc/uri-field.txt
@@ -129,39 +129,40 @@ in a normalised form.
The default behaviour is to allow both cases:
>>> with_slash = IURIFieldTest['with_slash']
- >>> with_slash.normalize(u'http://launchpad.net/ubuntu/')
- u'http://launchpad.net/ubuntu/'
- >>> with_slash.normalize(u'http://launchpad.net/ubuntu/?query#fragment')
- u'http://launchpad.net/ubuntu/?query#fragment'
- >>> with_slash.normalize(u'http://launchpad.net/ubuntu')
- u'http://launchpad.net/ubuntu/'
- >>> with_slash.normalize(u'http://launchpad.net')
- u'http://launchpad.net/'
+ >>> print(with_slash.normalize(u'http://launchpad.net/ubuntu/'))
+ http://launchpad.net/ubuntu/
+ >>> print(with_slash.normalize(
+ ... u'http://launchpad.net/ubuntu/?query#fragment'))
+ http://launchpad.net/ubuntu/?query#fragment
+ >>> print(with_slash.normalize(u'http://launchpad.net/ubuntu'))
+ http://launchpad.net/ubuntu/
+ >>> print(with_slash.normalize(u'http://launchpad.net'))
+ http://launchpad.net/
Similarly, we can require that the URI path does not end in a slash:
>>> without_slash = IURIFieldTest['without_slash']
- >>> without_slash.normalize(u'http://launchpad.net/ubuntu')
- u'http://launchpad.net/ubuntu'
- >>> without_slash.normalize(u'http://launchpad.net/ubuntu/#fragment')
- u'http://launchpad.net/ubuntu#fragment'
- >>> without_slash.normalize(u'http://launchpad.net/ubuntu#fragment/')
- u'http://launchpad.net/ubuntu#fragment/'
- >>> without_slash.normalize(u'http://launchpad.net/ubuntu/')
- u'http://launchpad.net/ubuntu'
+ >>> print(without_slash.normalize(u'http://launchpad.net/ubuntu'))
+ http://launchpad.net/ubuntu
+ >>> print(without_slash.normalize(u'http://launchpad.net/ubuntu/#fragment'))
+ http://launchpad.net/ubuntu#fragment
+ >>> print(without_slash.normalize(u'http://launchpad.net/ubuntu#fragment/'))
+ http://launchpad.net/ubuntu#fragment/
+ >>> print(without_slash.normalize(u'http://launchpad.net/ubuntu/'))
+ http://launchpad.net/ubuntu
URIs with an authority but a blank path get canonicalised to a path of
"/", which is not affected by the without_slash setting.
- >>> with_slash.normalize(u'http://launchpad.net/')
- u'http://launchpad.net/'
- >>> with_slash.normalize(u'http://launchpad.net')
- u'http://launchpad.net/'
+ >>> print(with_slash.normalize(u'http://launchpad.net/'))
+ http://launchpad.net/
+ >>> print(with_slash.normalize(u'http://launchpad.net'))
+ http://launchpad.net/
- >>> without_slash.normalize(u'http://launchpad.net/')
- u'http://launchpad.net/'
- >>> without_slash.normalize(u'http://launchpad.net')
- u'http://launchpad.net/'
+ >>> print(without_slash.normalize(u'http://launchpad.net/'))
+ http://launchpad.net/
+ >>> print(without_slash.normalize(u'http://launchpad.net'))
+ http://launchpad.net/
== Null values ==
@@ -208,5 +209,5 @@ Multiple values will cause an UnexpectedFormData exception:
Values with leading and trailing whitespace are stripped.
- >>> widget._toFieldValue(' http://www.ubuntu.com/ ')
- u'http://www.ubuntu.com/'
+ >>> print(widget._toFieldValue(' http://www.ubuntu.com/ '))
+ http://www.ubuntu.com/
diff --git a/lib/lp/services/geoip/doc/geoip.txt b/lib/lp/services/geoip/doc/geoip.txt
index 8767ee2..aeba9fb 100644
--- a/lib/lp/services/geoip/doc/geoip.txt
+++ b/lib/lp/services/geoip/doc/geoip.txt
@@ -11,8 +11,8 @@ from a given IP address.
The getCountryByAddr() method will return the country of the given IP
address.
- >>> geoip.getCountryByAddr('201.13.165.145').name
- u'Brazil'
+ >>> print(geoip.getCountryByAddr('201.13.165.145').name)
+ Brazil
When running tests the IP address will start with '127.', and GeoIP
would, obviously, fail to find the country for that, so we return None.
diff --git a/lib/lp/services/gpg/doc/gpg-encryption.txt b/lib/lp/services/gpg/doc/gpg-encryption.txt
index d26a497..d453e14 100644
--- a/lib/lp/services/gpg/doc/gpg-encryption.txt
+++ b/lib/lp/services/gpg/doc/gpg-encryption.txt
@@ -26,8 +26,8 @@ Sample Person has public and secret keys set.
True
>>> login('test@xxxxxxxxxxxxx')
- >>> bag.user.name
- u'name12'
+ >>> print(bag.user.name)
+ name12
>>> from lp.services.gpg.interfaces import IGPGHandler
>>> gpghandler = getUtility(IGPGHandler)
@@ -46,8 +46,8 @@ property, since both are generating using GPGKeyset.getGPGKeys)
Note fingerprint is also unicode.
- >>> fingerprint
- u'A419AE861E88BC9E04B9C26FBA2B9389DFD20543'
+ >>> print(fingerprint)
+ A419AE861E88BC9E04B9C26FBA2B9389DFD20543
>>> key = gpghandler.retrieveKey(fingerprint)
>>> cipher = gpghandler.encryptContent(content.encode('utf-8'), key)
@@ -62,16 +62,16 @@ only way we can decrypt the cipher content.
voilá, the same content shows up again.
- >>> plain.decode('utf-8')
- u'\ufcber'
+ >>> print(backslashreplace(plain.decode('utf-8')))
+ \ufcber
Verify if the encrytion process support passing another charset string
>>> content = u'a\xe7ucar'
>>> cipher = gpghandler.encryptContent(content.encode('iso-8859-1'), key)
>>> plain = decrypt_content(cipher, 'test')
- >>> plain.decode('iso-8859-1')
- u'a\xe7ucar'
+ >>> print(backslashreplace(plain.decode('iso-8859-1')))
+ a\xe7ucar
Let's try to pass unicode and see if it fails
diff --git a/lib/lp/services/gpg/doc/gpg-signatures.txt b/lib/lp/services/gpg/doc/gpg-signatures.txt
index 6ba60df..2f98077 100644
--- a/lib/lp/services/gpg/doc/gpg-signatures.txt
+++ b/lib/lp/services/gpg/doc/gpg-signatures.txt
@@ -20,8 +20,8 @@ OpenPGP Signature Verification
True
>>> login('test@xxxxxxxxxxxxx')
- >>> bag.user.name
- u'name12'
+ >>> print(bag.user.name)
+ name12
>>> from zope.component import getUtility
>>> from lp.services.gpg.interfaces import IGPGHandler
diff --git a/lib/lp/services/helpers.py b/lib/lp/services/helpers.py
index b102871..f676e61 100644
--- a/lib/lp/services/helpers.py
+++ b/lib/lp/services/helpers.py
@@ -42,8 +42,11 @@ def text_replaced(text, replacements, _cache={}):
Unicode strings work too.
- >>> text_replaced(u'1 2 3 4', {u'1': u'2', u'2': u'1'})
- u'2 1 3 4'
+ >>> replaced = text_replaced(u'1 2 3 4', {u'1': u'2', u'2': u'1'})
+ >>> isinstance(replaced, six.text_type)
+ True
+ >>> print(replaced)
+ 2 1 3 4
The argument _cache is used as a cache of replacements that were requested
before, so we only compute regular expressions once.
diff --git a/lib/lp/services/identity/doc/account.txt b/lib/lp/services/identity/doc/account.txt
index b9eabb1..f12fd42 100644
--- a/lib/lp/services/identity/doc/account.txt
+++ b/lib/lp/services/identity/doc/account.txt
@@ -125,8 +125,8 @@ database. Only an admin can change the status.
An Account has at least one OpenID identifier used to generate the
OpenID identity URL.
- >>> account.openid_identifiers.any().identifier
- u'no-priv_oid'
+ >>> print(account.openid_identifiers.any().identifier)
+ no-priv_oid
Creating new accounts
diff --git a/lib/lp/services/identity/doc/emailaddress.txt b/lib/lp/services/identity/doc/emailaddress.txt
index 5d8d9d6..607250b 100644
--- a/lib/lp/services/identity/doc/emailaddress.txt
+++ b/lib/lp/services/identity/doc/emailaddress.txt
@@ -53,8 +53,8 @@ Registering a new email address works -- and preserves case -- though:
>>> emailaddress = emailset.new(
... 'oink@xxxxxxxxxxxxx', foobar)
- >>> emailaddress.email
- u'oink@xxxxxxxxxxxxx'
+ >>> print(emailaddress.email)
+ oink@xxxxxxxxxxxxx
Generating SHA1 hashes for RDF output is easy:
@@ -65,13 +65,19 @@ There's a convenience method on IEmailAddressSet to pull preferred email
addresses for a set of people:
>>> guadamen = personset.getByName('guadamen')
- >>> [emailaddress.email for emailaddress in
- ... emailset.getPreferredEmailForPeople(guadamen.allmembers)]
- [u'celso.providelo@xxxxxxxxxxxxx', u'colin.watson@xxxxxxxxxxxxxxx',
- u'daniel.silverstone@xxxxxxxxxxxxx', u'edgar@xxxxxxxxxxxxxxxx',
- u'foo.bar@xxxxxxxxxxxxx', u'jeff.waugh@xxxxxxxxxxxxxxx',
- u'limi@xxxxxxxxx', u'mark@xxxxxxxxxxx',
- u'steve.alexander@xxxxxxxxxxxxxxx', u'support@xxxxxxxxxx']
+ >>> for emailaddress in emailset.getPreferredEmailForPeople(
+ ... guadamen.allmembers):
+ ... print(emailaddress.email)
+ celso.providelo@xxxxxxxxxxxxx
+ colin.watson@xxxxxxxxxxxxxxx
+ daniel.silverstone@xxxxxxxxxxxxx
+ edgar@xxxxxxxxxxxxxxxx
+ foo.bar@xxxxxxxxxxxxx
+ jeff.waugh@xxxxxxxxxxxxxxx
+ limi@xxxxxxxxx
+ mark@xxxxxxxxxxx
+ steve.alexander@xxxxxxxxxxxxxxx
+ support@xxxxxxxxxx
Deleting email addresses
diff --git a/lib/lp/services/mail/doc/notification-recipient-set.txt b/lib/lp/services/mail/doc/notification-recipient-set.txt
index a1030ee..059cd7b 100644
--- a/lib/lp/services/mail/doc/notification-recipient-set.txt
+++ b/lib/lp/services/mail/doc/notification-recipient-set.txt
@@ -49,8 +49,10 @@ existing values if they apply to your context.
The getPersons() method returns the list of recipients sorted by display
name.
- >>> [person.displayname for person in recipients.getRecipients()]
- [u'Celso Providelo', u'Sample Person']
+ >>> for person in recipients.getRecipients():
+ ... print(person.displayname)
+ Celso Providelo
+ Sample Person
It's also possible to iterate over the recipients:
@@ -152,8 +154,11 @@ person:
>>> 'support@xxxxxxxxxx' in recipients
True
- >>> [person.displayname for person in recipients]
- [u'Celso Providelo', u'Sample Person', u'Ubuntu Team']
+ >>> for person in recipients:
+ ... print(person.displayname)
+ Celso Providelo
+ Sample Person
+ Ubuntu Team
>>> recipients.getEmails()
['celso.providelo@xxxxxxxxxxxxx', 'support@xxxxxxxxxx',
@@ -180,8 +185,9 @@ addresses are added to the recipients list, and this recursively.
But looking at the recipients list, only the team is listed:
- >>> [person.displayname for person in recipients]
- [u'Ubuntu Gnome Team']
+ >>> for person in recipients:
+ ... print(person.displayname)
+ Ubuntu Gnome Team
So Sample Person is not in the recipients list, even if their email will
be notified for they're a member of Warty Security Team, itself a member of
@@ -224,8 +230,10 @@ be added with the same rationale:
>>> recipients = NotificationRecipientSet()
>>> recipients.add(
... [sample_person, no_priv], 'Notified for fun.', 'Fun')
- >>> [person.displayname for person in recipients.getRecipients()]
- [u'No Privileges Person', u'Sample Person']
+ >>> for person in recipients.getRecipients():
+ ... print(person.displayname)
+ No Privileges Person
+ Sample Person
>>> print_reason(recipients.getReason(no_priv))
Fun (Notified for fun.)
@@ -243,12 +251,16 @@ NotificationRecipientSet():
>>> recipients = NotificationRecipientSet()
>>> recipients.add(
... [sample_person, no_priv, cprov], 'Notified for fun.', 'Fun')
- >>> [person.displayname for person in recipients.getRecipients()]
- [u'Celso Providelo', u'No Privileges Person', u'Sample Person']
+ >>> for person in recipients.getRecipients():
+ ... print(person.displayname)
+ Celso Providelo
+ No Privileges Person
+ Sample Person
>>> recipients.remove([sample_person, cprov])
- >>> [person.displayname for person in recipients.getRecipients()]
- [u'No Privileges Person']
+ >>> for person in recipients.getRecipients():
+ ... print(person.displayname)
+ No Privileges Person
>>> recipients.getEmails()
['no-priv@xxxxxxxxxxxxx']
diff --git a/lib/lp/services/mail/doc/sending-mail.txt b/lib/lp/services/mail/doc/sending-mail.txt
index f4f0e7f..88bf4c9 100644
--- a/lib/lp/services/mail/doc/sending-mail.txt
+++ b/lib/lp/services/mail/doc/sending-mail.txt
@@ -73,8 +73,8 @@ simple_sendmail_from_person uses the Person's preferred email address:
... 'testing@xxxxxxxxxxxxx')
>>> sample_person.setPreferredEmail(testing)
- >>> sample_person.preferredemail.email
- u'testing@xxxxxxxxxxxxx'
+ >>> print(sample_person.preferredemail.email)
+ testing@xxxxxxxxxxxxx
>>> msgid = simple_sendmail_from_person(
... person=sample_person,
... to_addrs='test@xxxxxxxxxxxxx',
@@ -131,11 +131,12 @@ Now let's look at the sent email again.
>>> from email.header import decode_header
>>> subject_str, charset = decode_header(msg['Subject'])[0]
- >>> subject_str.decode(charset)
- u'\xc4mnesrad'
+ >>> print(backslashreplace(subject_str.decode(charset)))
+ \xc4mnesrad
- >>> msg.get_payload(decode=True).decode(msg.get_content_charset())
- u'Inneh\xe5ll'
+ >>> print(backslashreplace(
+ ... msg.get_payload(decode=True).decode(msg.get_content_charset())))
+ Inneh\xe5ll
If we use simple_sendmail_from_person, the person's display_name can
@@ -158,15 +159,16 @@ contain non-ASCII characters:
>>> from_name_str, charset = decode_header(from_name_encoded)[0]
>>> from_addr
'foo.bar@xxxxxxxxxxxxx'
- >>> from_name_str.decode(charset)
- u'F\xf6\xf6 B\u0105r'
+ >>> print(backslashreplace(from_name_str.decode(charset)))
+ F\xf6\xf6 B\u0105r
>>> subject_str, charset = decode_header(msg['Subject'])[0]
- >>> subject_str.decode(charset)
- u'\xc4mnesrad'
+ >>> print(backslashreplace(subject_str.decode(charset)))
+ \xc4mnesrad
- >>> msg.get_payload(decode=True).decode(msg.get_content_charset())
- u'Inneh\xe5ll'
+ >>> print(backslashreplace(
+ ... msg.get_payload(decode=True).decode(msg.get_content_charset())))
+ Inneh\xe5ll
simple_sendmail_from_person also makes sure that the name gets
surrounded by quotes and quoted if necessary:
diff --git a/lib/lp/services/messages/doc/message.txt b/lib/lp/services/messages/doc/message.txt
index 3113703..06d63e5 100644
--- a/lib/lp/services/messages/doc/message.txt
+++ b/lib/lp/services/messages/doc/message.txt
@@ -16,15 +16,15 @@ on bugs. Bugs are linked to Messages via the BugMessage table.
... subject='The Title', content='The Content', bug=bug_one,
... owner=current_user)
>>> msg = bmsg.message
- >>> msg.subject
- u'The Title'
+ >>> print(msg.subject)
+ The Title
We can retrieve the text chunks as a unicode string. (However, note that
if generating HTML you should use the MessageChunks detailed below
to handle attachments correctly)
- >>> msg.text_contents
- u'The Content'
+ >>> print(msg.text_contents)
+ The Content
Messages are threaded, although this is not necessarily displayed in the
UI. Each message has a parent attribute. If the message was created via
@@ -52,8 +52,8 @@ may be accessed using the chunks attribute, or simply by iterating over
the Message.
>>> for chunk in msg:
- ... print repr([chunk.sequence, chunk.content, chunk.blob])
- [1, u'The Content', None]
+ ... print pretty([chunk.sequence, chunk.content, chunk.blob])
+ [1, 'The Content', None]
>>> msg.chunks[0].message == msg
True
@@ -124,20 +124,22 @@ normal.
>>> msg = msg_set.get(
... rfc822msgid="<20050405054002.22134.71562@localhost.localdomain>"
... )[0]
- >>> msg.title
- u'Unicode\u2122'
+ >>> print(msg.title)
+ Unicode™
>>> chunks = msg.chunks
>>> for chunk in chunks:
... if chunk.content:
- ... print '%2d - %r' % (chunk.sequence, chunk.content)
- 1 - u'Plain text'
- 3 - u'Unicode\u2122 text'
+ ... print '%2d - %s' % (chunk.sequence, pretty(chunk.content))
+ 1 - 'Plain text'
+ 3 - 'Unicode\u2122 text'
The text_contents attribute contains only the text parts, since that is
what we want to display in the UI.
- >>> msg.text_contents
- u'Plain text\n\nUnicode\u2122 text'
+ >>> print(msg.text_contents)
+ Plain text
+ <BLANKLINE>
+ Unicode™ text
Stripping non-text parts is useful, since a lot of messages will contain
detach GPG signatures, and they shouldn't be shown in the UI since they
@@ -176,16 +178,16 @@ of type text/plain, so are stored as blobs.
>>> chunks[1].content is None
True
>>> blob = chunks[1].blob
- >>> blob.filename
- u'anna.jpg.exe'
+ >>> print(blob.filename)
+ anna.jpg.exe
>>> blob.http_url.endswith(u'/anna.jpg.exe')
True
>>> blob2 = chunks[3].blob
- >>> blob2.filename
- u'unnamed'
- >>> blob2.mimetype
- u'application/xml; charset="utf16"'
+ >>> print(blob2.filename)
+ unnamed
+ >>> print(blob2.mimetype)
+ application/xml; charset="utf16"
Only those chunks of content type text/plain with content-disposition
"inline" that have no filename are stored as content. If an inline
@@ -251,12 +253,12 @@ used as a default.
>>> msg = msgset.fromEmail(raw_msg)
>>> for chunk in msg.chunks:
... if chunk.content is not None:
- ... print '%d - %r' % (chunk.sequence, chunk.content)
+ ... print '%d - %s' % (chunk.sequence, pretty(chunk.content))
... else:
... print '%d - file: %s (%s)' % (
... chunk.sequence, chunk.blob.filename, chunk.blob.mimetype)
- 1 - u'Plain text'
- 2 - u'Plain text without a ch\xc4\x83\xc5\x95\xc5\x9d\xc4\x9b\xc5\xa3.'
+ 1 - 'Plain text'
+ 2 - 'Plain text without a ch\xc4\x83\xc5\x95\xc5\x9d\xc4\x9b\xc5\xa3.'
3 - file: attachment.txt (text/plain; charset="us-ascii")
4 - file: unnamed (text/plain; charset="us-ascii")
5 - file: attachment2.txt (text/plain; charset="us-ascii")
@@ -270,8 +272,9 @@ as the request. I don't think this is important outside of tests.
>>> blob.read()
'\x00\x01\x02\x03'
- >>> blob2.read().decode('utf16')
- u'<?xml version="1.0" encoding="utf16"?>\n<unicode>\u2122</unicode>'
+ >>> print(blob2.read().decode('utf16'))
+ <?xml version="1.0" encoding="utf16"?>
+ <unicode>™</unicode>
We can also retrieve a byte-identical copy of the original message
@@ -349,13 +352,14 @@ quite happily.
...
... Foo Bar
... ''')
- >>> msg.title
- u'Test'
+ >>> print(msg.title)
+ Test
>>> chunks = list(msg.chunks)
>>> len(chunks)
1
- >>> chunks[0].content
- u'Foo Bar\n'
+ >>> print(chunks[0].content)
+ Foo Bar
+ <BLANKLINE>
It also handles the case where the subject line is folded.
@@ -369,8 +373,8 @@ It also handles the case where the subject line is folded.
... Foo Bar
... ''')
- >>> msg.title
- u'Folded subject'
+ >>> print(msg.title)
+ Folded subject
However, there are some things it refuses to deal with. In particular, it
@@ -398,8 +402,8 @@ explicitly told to do so:
...
... Foo Bar
... ''', create_missing_persons=True)
- >>> msg.subject
- u'Foo Bar Bazarooney!'
+ >>> print(msg.subject)
+ Foo Bar Bazarooney!
When the fromEmail() method creates a new Person entry, it'll set the
creation_rationale accordingly.
diff --git a/lib/lp/services/oauth/doc/oauth-pages.txt b/lib/lp/services/oauth/doc/oauth-pages.txt
index 8c29dc9..5b9cd98 100644
--- a/lib/lp/services/oauth/doc/oauth-pages.txt
+++ b/lib/lp/services/oauth/doc/oauth-pages.txt
@@ -71,8 +71,8 @@ context either.
oauth_token...
>>> view.reviewToken(OAuthPermission.READ_PRIVATE, None)
- >>> token.person.name
- u'salgado'
+ >>> print(token.person.name)
+ salgado
>>> print(token.context)
None
>>> token.permission
@@ -84,8 +84,8 @@ The context can be a product, and if it's specified it will be carried
over to the token once it's reviewed.
>>> view, token = get_view_with_fresh_token({'lp.context': 'firefox'})
- >>> view.token_context.name
- u'firefox'
+ >>> print(view.token_context.name)
+ firefox
# The context is also stored in a hidden field in the HTML so that
# it's submitted together with the user's chosen permission.
@@ -95,14 +95,14 @@ over to the token once it's reviewed.
lp.context firefox
>>> view.reviewToken(OAuthPermission.READ_PUBLIC, None)
- >>> token.context.name
- u'firefox'
+ >>> print(token.context.name)
+ firefox
Likewise for a project.
>>> view, token = get_view_with_fresh_token({'lp.context': 'mozilla'})
- >>> view.token_context.name
- u'mozilla'
+ >>> print(view.token_context.name)
+ mozilla
# The context is also stored in a hidden field in the HTML so that
# it's submitted together with the user's chosen permission.
@@ -112,14 +112,14 @@ Likewise for a project.
lp.context mozilla
>>> view.reviewToken(OAuthPermission.READ_PUBLIC, None)
- >>> token.context.name
- u'mozilla'
+ >>> print(token.context.name)
+ mozilla
And a distribution.
>>> view, token = get_view_with_fresh_token({'lp.context': 'ubuntu'})
- >>> view.token_context.name
- u'ubuntu'
+ >>> print(view.token_context.name)
+ ubuntu
# The context is also stored in a hidden field in the HTML so that
# it's submitted together with the user's chosen permission.
@@ -129,16 +129,16 @@ And a distribution.
lp.context ubuntu
>>> view.reviewToken(OAuthPermission.READ_PUBLIC, None)
- >>> token.context.name
- u'ubuntu'
+ >>> print(token.context.name)
+ ubuntu
If the consumer wants to access only things related to a distribution's
package, it must specify the distribution and the package's name.
>>> view, token = get_view_with_fresh_token(
... {'lp.context': 'ubuntu/evolution'})
- >>> view.token_context.title
- u'...evolution... package in Ubuntu'
+ >>> print(view.token_context.title)
+ evolution package in Ubuntu
# The context is also stored in a hidden field in the HTML so that
# it's submitted together with the user's chosen permission.
@@ -148,8 +148,8 @@ package, it must specify the distribution and the package's name.
lp.context ubuntu/evolution
>>> view.reviewToken(OAuthPermission.READ_PUBLIC, None)
- >>> token.context.title
- u'...evolution... package in Ubuntu'
+ >>> print(token.context.title)
+ evolution package in Ubuntu
An error is raised if the context is not found.
diff --git a/lib/lp/services/oauth/stories/authorize-token.txt b/lib/lp/services/oauth/stories/authorize-token.txt
index e217b8a..23f4911 100644
--- a/lib/lp/services/oauth/stories/authorize-token.txt
+++ b/lib/lp/services/oauth/stories/authorize-token.txt
@@ -198,8 +198,8 @@ person set.
# transaction.
>>> login(ANONYMOUS)
>>> token = consumer.getRequestToken(token.key)
- >>> token.person.name
- u'no-priv'
+ >>> print(token.person.name)
+ no-priv
>>> token.permission
<DBItem OAuthPermission.READ_PUBLIC...
>>> token.is_reviewed
diff --git a/lib/lp/services/verification/doc/logintoken.txt b/lib/lp/services/verification/doc/logintoken.txt
index 3f3a50a..14e6335 100644
--- a/lib/lp/services/verification/doc/logintoken.txt
+++ b/lib/lp/services/verification/doc/logintoken.txt
@@ -56,8 +56,9 @@ As the process is not yet finished, foobar will see this as one of their
unconfirmed email addresses.
>>> flush_database_updates()
- >>> foobar.unvalidatedemails
- [u'foo.bar2@xxxxxxxxxxxxx']
+ >>> for email in foobar.unvalidatedemails:
+ ... print(email)
+ foo.bar2@xxxxxxxxxxxxx
It's possible to create another token for the same purpose, but this
won't cause that email to show up twice on foobar's list of unconfirmed
@@ -67,8 +68,9 @@ emails.
... foobar, 'foo.bar@xxxxxxxxxxxxx', 'foo.bar2@xxxxxxxxxxxxx',
... LoginTokenType.VALIDATEEMAIL)
>>> flush_database_updates()
- >>> foobar.unvalidatedemails
- [u'foo.bar2@xxxxxxxxxxxxx']
+ >>> for email in foobar.unvalidatedemails:
+ ... print(email)
+ foo.bar2@xxxxxxxxxxxxx
Once foobar finished the process, confirming their new email address, we
mark the token as consumed.
@@ -113,8 +115,9 @@ our own making.
... LoginTokenType.VALIDATEEMAIL)
>>> flush_database_updates()
- >>> foobar.unvalidatedemails
- [u'foo.bar2@xxxxxxxxxxxxx']
+ >>> for email in foobar.unvalidatedemails:
+ ... print(email)
+ foo.bar2@xxxxxxxxxxxxx
>>> token3.consume()
>>> token3.date_consumed is not None
diff --git a/lib/lp/services/webapp/doc/canonical_url.txt b/lib/lp/services/webapp/doc/canonical_url.txt
index ba277c9..2730fa2 100644
--- a/lib/lp/services/webapp/doc/canonical_url.txt
+++ b/lib/lp/services/webapp/doc/canonical_url.txt
@@ -132,8 +132,8 @@ Now, there is an ICanonicalUrlData registered for ITown.
>>> from lp.testing import verifyObject
>>> verifyObject(ICanonicalUrlData, town_urldata)
True
- >>> town_urldata.path
- u'+towns/London'
+ >>> print(town_urldata.path)
+ +towns/London
>>> town_urldata.inside is country_instance
True
@@ -248,14 +248,14 @@ stitching together the various ICanonicalUrlData adapters for that object
and the objects it is inside of (or in other words, hierarchically below).
>>> from lp.services.webapp import canonical_url
- >>> canonical_url(getUtility(ILaunchpadRoot))
- u'http://launchpad.test/'
- >>> canonical_url(countryset_instance)
- u'http://launchpad.test/countries'
- >>> canonical_url(country_instance)
- u'http://launchpad.test/countries/England'
- >>> canonical_url(town_instance)
- u'http://launchpad.test/countries/England/+towns/London'
+ >>> print(canonical_url(getUtility(ILaunchpadRoot)))
+ http://launchpad.test/
+ >>> print(canonical_url(countryset_instance))
+ http://launchpad.test/countries
+ >>> print(canonical_url(country_instance))
+ http://launchpad.test/countries/England
+ >>> print(canonical_url(town_instance))
+ http://launchpad.test/countries/England/+towns/London
We can see that this is the mainsite rooturl as configured in launchpad.conf.
@@ -375,20 +375,20 @@ zope.publisher.interfaces.http.IHTTPApplicationRequest.
... return self.applicationurl
>>> mandrill_request = FakeRequest('https://mandrill.example.org:23')
- >>> canonical_url(country_instance)
- u'http://launchpad.test/countries/England'
- >>> canonical_url(country_instance, mandrill_request)
- u'https://mandrill.example.org:23/countries/England'
+ >>> print(canonical_url(country_instance))
+ http://launchpad.test/countries/England
+ >>> print(canonical_url(country_instance, mandrill_request))
+ https://mandrill.example.org:23/countries/England
However, if we log in, then that request should be used when none is explicitly
given otherwise.
>>> sesame_request = FakeRequest('http://muppet.example.com')
>>> login(ANONYMOUS, sesame_request)
- >>> canonical_url(country_instance)
- u'http://muppet.example.com/countries/England'
- >>> canonical_url(country_instance, mandrill_request)
- u'https://mandrill.example.org:23/countries/England'
+ >>> print(canonical_url(country_instance))
+ http://muppet.example.com/countries/England
+ >>> print(canonical_url(country_instance, mandrill_request))
+ https://mandrill.example.org:23/countries/England
== canonical_url and overriding rootsite ==
@@ -402,10 +402,10 @@ a rootsite.
Overriding the rootsite from the default request:
- >>> canonical_url(country_instance)
- u'http://muppet.example.com/countries/England'
- >>> canonical_url(country_instance, rootsite='code')
- u'http://code.launchpad.test/countries/England'
+ >>> print(canonical_url(country_instance))
+ http://muppet.example.com/countries/England
+ >>> print(canonical_url(country_instance, rootsite='code'))
+ http://code.launchpad.test/countries/England
Webapp vhost overrides can be ignored by setting the
app.mainsite_only.canonical_url feature flag, so all links end up on
@@ -413,17 +413,18 @@ mainsite. Non-webapp vhosts (eg. api and feeds) are unaffected.
>>> from lp.services.features.testing import MemoryFeatureFixture
>>> with MemoryFeatureFixture({'app.mainsite_only.canonical_url': 'on'}):
- ... canonical_url(country_instance, rootsite='code')
- ... canonical_url(country_instance, rootsite='api')
- u'http://launchpad.test/countries/England'
- u'http://api.launchpad.test/countries/England'
+ ... print(canonical_url(country_instance, rootsite='code'))
+ ... print(canonical_url(country_instance, rootsite='api'))
+ http://launchpad.test/countries/England
+ http://api.launchpad.test/countries/England
Overriding the rootsite from the specified request:
- >>> canonical_url(country_instance, mandrill_request)
- u'https://mandrill.example.org:23/countries/England'
- >>> canonical_url(country_instance, mandrill_request, rootsite='code')
- u'http://code.launchpad.test/countries/England'
+ >>> print(canonical_url(country_instance, mandrill_request))
+ https://mandrill.example.org:23/countries/England
+ >>> print(canonical_url(
+ ... country_instance, mandrill_request, rootsite='code'))
+ http://code.launchpad.test/countries/England
And if the configuration does provide a rootsite:
@@ -446,15 +447,16 @@ And if the configuration does provide a rootsite:
... </configure>
... """.format(module_name=module.__name__))
- >>> canonical_url(country_instance)
- u'http://bugs.launchpad.test/countries/England'
- >>> canonical_url(country_instance, rootsite='code')
- u'http://code.launchpad.test/countries/England'
- >>> canonical_url(country_instance, mandrill_request, rootsite='code')
- u'http://code.launchpad.test/countries/England'
+ >>> print(canonical_url(country_instance))
+ http://bugs.launchpad.test/countries/England
+ >>> print(canonical_url(country_instance, rootsite='code'))
+ http://code.launchpad.test/countries/England
+ >>> print(canonical_url(
+ ... country_instance, mandrill_request, rootsite='code'))
+ http://code.launchpad.test/countries/England
>>> with MemoryFeatureFixture({'app.mainsite_only.canonical_url': 'on'}):
- ... canonical_url(country_instance)
- u'http://launchpad.test/countries/England'
+ ... print(canonical_url(country_instance))
+ http://launchpad.test/countries/England
== canonical_url and named views ==
@@ -462,20 +464,20 @@ And if the configuration does provide a rootsite:
The url for a particular view of an object can be generated by specifying
the view's name.
- >>> canonical_url(country_instance, view_name="+map")
- u'http://bugs.launchpad.test/countries/England/+map'
+ >>> print(canonical_url(country_instance, view_name="+map"))
+ http://bugs.launchpad.test/countries/England/+map
view_name also works when the view_name refers to a Navigation stepto,
stepthrough, or redirection:
- >>> canonical_url(country_instance, view_name="+greenwich")
- u'http://bugs.launchpad.test/countries/England/+greenwich'
+ >>> print(canonical_url(country_instance, view_name="+greenwich"))
+ http://bugs.launchpad.test/countries/England/+greenwich
- >>> canonical_url(country_instance, view_name="+capital")
- u'http://bugs.launchpad.test/countries/England/+capital'
+ >>> print(canonical_url(country_instance, view_name="+capital"))
+ http://bugs.launchpad.test/countries/England/+capital
- >>> canonical_url(country_instance, view_name="+towns")
- u'http://bugs.launchpad.test/countries/England/+towns'
+ >>> print(canonical_url(country_instance, view_name="+towns"))
+ http://bugs.launchpad.test/countries/England/+towns
Giving an unregistered view name will trigger an assertion failure.
@@ -525,15 +527,15 @@ a web service request
>>> get_current_browser_request() is api_request
True
- >>> canonical_url(countryset_instance)
- u'http://launchpad.test/countries'
+ >>> print(canonical_url(countryset_instance))
+ http://launchpad.test/countries
If an URL that can be used in the web service is required, a web service
request has to be passed in explicitly.
- >>> canonical_url(countryset_instance, request=api_request)
- u'http://api.launchpad.test/countries'
+ >>> print(canonical_url(countryset_instance, request=api_request))
+ http://api.launchpad.test/countries
It is often the case that the web application wants to provide URLs that will
be written out onto the pages that the Javascript can process using the
@@ -541,8 +543,8 @@ LP.client code to get access to the object entries using the API. In these
cases, the "force_local_path" parameter can be passed to canonical_url to have
only the relative local path returned.
- >>> canonical_url(countryset_instance, force_local_path=True)
- u'/countries'
+ >>> print(canonical_url(countryset_instance, force_local_path=True))
+ /countries
== The end ==
diff --git a/lib/lp/services/webapp/doc/canonical_url_examples.txt b/lib/lp/services/webapp/doc/canonical_url_examples.txt
index 6db9c6a..ec107a5 100644
--- a/lib/lp/services/webapp/doc/canonical_url_examples.txt
+++ b/lib/lp/services/webapp/doc/canonical_url_examples.txt
@@ -29,23 +29,23 @@ Application homepages
The Launchpad homepage.
- >>> canonical_url(getUtility(ILaunchpadRoot))
- u'http://launchpad.test/'
+ >>> print(canonical_url(getUtility(ILaunchpadRoot)))
+ http://launchpad.test/
The Malone homepage.
- >>> canonical_url(getUtility(IMaloneApplication))
- u'http://launchpad.test/bugs'
+ >>> print(canonical_url(getUtility(IMaloneApplication)))
+ http://launchpad.test/bugs
The Bazaar homepage.
- >>> canonical_url(getUtility(IBazaarApplication))
- u'http://code.launchpad.test/+code'
+ >>> print(canonical_url(getUtility(IBazaarApplication)))
+ http://code.launchpad.test/+code
The Answer Tracker
- >>> canonical_url(getUtility(IQuestionSet))
- u'http://answers.launchpad.test/questions'
+ >>> print(canonical_url(getUtility(IQuestionSet)))
+ http://answers.launchpad.test/questions
Launchpad Translations (Rosetta) canonical_url examples are in
lib/lp/translations/doc/canonical_url_examples.txt.
@@ -62,40 +62,40 @@ Persons and Teams
The IPersonSet.
- >>> canonical_url(getUtility(IPersonSet))
- u'http://launchpad.test/people'
+ >>> print(canonical_url(getUtility(IPersonSet)))
+ http://launchpad.test/people
An IPerson.
- >>> canonical_url(getUtility(IPersonSet).getByName('mark'))
- u'http://launchpad.test/~mark'
+ >>> print(canonical_url(getUtility(IPersonSet).getByName('mark')))
+ http://launchpad.test/~mark
An ITeam.
- >>> canonical_url(celebs.rosetta_experts)
- u'http://launchpad.test/~rosetta-admins'
+ >>> print(canonical_url(celebs.rosetta_experts))
+ http://launchpad.test/~rosetta-admins
An ICodeOfConductSet
>>> cocset = getUtility(ICodeOfConductSet)
- >>> canonical_url(cocset)
- u'http://launchpad.test/codeofconduct'
+ >>> print(canonical_url(cocset))
+ http://launchpad.test/codeofconduct
An ISignedCodeOfConductSet
>>> signedcocset = getUtility(ISignedCodeOfConductSet)
- >>> canonical_url(signedcocset)
- u'http://launchpad.test/codeofconduct/console'
+ >>> print(canonical_url(signedcocset))
+ http://launchpad.test/codeofconduct/console
An ISignedCodeOfConduct
- >>> canonical_url(signedcocset['1'])
- u'http://launchpad.test/codeofconduct/console/1'
+ >>> print(canonical_url(signedcocset['1']))
+ http://launchpad.test/codeofconduct/console/1
An ICodeOfConduct
- >>> canonical_url(cocset['2.0'])
- u'http://launchpad.test/codeofconduct/2.0'
+ >>> print(canonical_url(cocset['2.0']))
+ http://launchpad.test/codeofconduct/2.0
Distributions, distroseriess and so on
@@ -107,24 +107,24 @@ The IDistributionSet.
>>> distroset = getUtility(IDistributionSet)
- >>> canonical_url(distroset)
- u'http://launchpad.test/distros'
+ >>> print(canonical_url(distroset))
+ http://launchpad.test/distros
An IDistribution.
- >>> canonical_url(celebs.ubuntu)
- u'http://launchpad.test/ubuntu'
+ >>> print(canonical_url(celebs.ubuntu))
+ http://launchpad.test/ubuntu
An IDistroSeries.
>>> hoary = celebs.ubuntu.getSeries('hoary')
- >>> canonical_url(hoary)
- u'http://launchpad.test/ubuntu/hoary'
+ >>> print(canonical_url(hoary))
+ http://launchpad.test/ubuntu/hoary
An ISourcePackage.
- >>> canonical_url(hoary.getSourcePackage('evolution'))
- u'http://launchpad.test/ubuntu/hoary/+source/evolution'
+ >>> print(canonical_url(hoary.getSourcePackage('evolution')))
+ http://launchpad.test/ubuntu/hoary/+source/evolution
An IDistributionSourcePackage.
@@ -133,8 +133,8 @@ An IDistributionSourcePackage.
>>> sourcepackagenameset = getUtility(ISourcePackageNameSet)
>>> ubuntu_firefox = celebs.ubuntu.getSourcePackage(
... sourcepackagenameset['mozilla-firefox'])
- >>> canonical_url(ubuntu_firefox)
- u'http://launchpad.test/ubuntu/+source/mozilla-firefox'
+ >>> print(canonical_url(ubuntu_firefox))
+ http://launchpad.test/ubuntu/+source/mozilla-firefox
Projects groups and products
@@ -145,37 +145,37 @@ Projects groups and products
The IProjectGroupSet.
- >>> canonical_url(getUtility(IProjectGroupSet))
- u'http://launchpad.test/projectgroups'
+ >>> print(canonical_url(getUtility(IProjectGroupSet)))
+ http://launchpad.test/projectgroups
An IProjectGroup.
- >>> canonical_url(getUtility(IProjectGroupSet)['apache'])
- u'http://launchpad.test/apache'
+ >>> print(canonical_url(getUtility(IProjectGroupSet)['apache']))
+ http://launchpad.test/apache
The IProductSet.
>>> productset = getUtility(IProductSet)
- >>> canonical_url(productset)
- u'http://launchpad.test/projects'
+ >>> print(canonical_url(productset))
+ http://launchpad.test/projects
An IProduct.
>>> evolution_product = productset['evolution']
- >>> canonical_url(evolution_product)
- u'http://launchpad.test/evolution'
+ >>> print(canonical_url(evolution_product))
+ http://launchpad.test/evolution
An IProductSeries.
>>> evolution_trunk_series = evolution_product.getSeries('trunk')
- >>> canonical_url(evolution_trunk_series)
- u'http://launchpad.test/evolution/trunk'
+ >>> print(canonical_url(evolution_trunk_series))
+ http://launchpad.test/evolution/trunk
An IProductRelease.
>>> evolution_release = evolution_trunk_series.getRelease('2.1.6')
- >>> canonical_url(evolution_release)
- u'http://launchpad.test/evolution/trunk/2.1.6'
+ >>> print(canonical_url(evolution_release))
+ http://launchpad.test/evolution/trunk/2.1.6
Bugs and bugtasks
@@ -186,34 +186,34 @@ Bugs and bugtasks
The IBugSet.
- >>> canonical_url(getUtility(IBugSet))
- u'http://launchpad.test/bugs/bugs'
+ >>> print(canonical_url(getUtility(IBugSet)))
+ http://launchpad.test/bugs/bugs
An IBug.
- >>> canonical_url(getUtility(IBugSet).get(1))
- u'http://bugs.launchpad.test/bugs/1'
+ >>> print(canonical_url(getUtility(IBugSet).get(1)))
+ http://bugs.launchpad.test/bugs/1
An IBugTask on a product.
- >>> canonical_url(getUtility(IBugTaskSet).get(2))
- u'http://bugs.launchpad.test/firefox/+bug/1'
+ >>> print(canonical_url(getUtility(IBugTaskSet).get(2)))
+ http://bugs.launchpad.test/firefox/+bug/1
An IMessage on a bug.
- >>> canonical_url(getUtility(IBugSet).get(1).messages[0])
- u'http://bugs.launchpad.test/firefox/+bug/1/comments/0'
+ >>> print(canonical_url(getUtility(IBugSet).get(1).messages[0]))
+ http://bugs.launchpad.test/firefox/+bug/1/comments/0
An IMessage on a question.
- >>> canonical_url(getUtility(IQuestionSet).get(6).messages[0])
- u'http://answers.launchpad.test/firefox/+question/6/messages/1'
+ >>> print(canonical_url(getUtility(IQuestionSet).get(6).messages[0]))
+ http://answers.launchpad.test/firefox/+question/6/messages/1
An IBugTask on a distribution source package.
>>> distro_task = getUtility(IBugTaskSet).get(4)
- >>> canonical_url(distro_task)
- u'http://bugs.launchpad.test/debian/+source/mozilla-firefox/+bug/1'
+ >>> print(canonical_url(distro_task))
+ http://bugs.launchpad.test/debian/+source/mozilla-firefox/+bug/1
An IBugTask on a distribution without a sourcepackage.
@@ -223,23 +223,23 @@ An IBugTask on a distribution without a sourcepackage.
>>> temp_target = distro_task.target
>>> distro_task.transitionToTarget(
... distro_task.target.distribution, getUtility(ILaunchBag).user)
- >>> canonical_url(distro_task)
- u'http://bugs.launchpad.test/debian/+bug/1'
+ >>> print(canonical_url(distro_task))
+ http://bugs.launchpad.test/debian/+bug/1
>>> distro_task.transitionToTarget(temp_target, getUtility(ILaunchBag).user)
An IBugTask on a distribution series source package.
>>> distro_series_task = getUtility(IBugTaskSet).get(19)
- >>> canonical_url(distro_series_task)
- u'http://bugs.launchpad.test/debian/sarge/+source/mozilla-firefox/+bug/3'
+ >>> print(canonical_url(distro_series_task))
+ http://bugs.launchpad.test/debian/sarge/+source/mozilla-firefox/+bug/3
An IBugTask on a distribution series without a sourcepackage.
>>> temp_target = distro_series_task.target
>>> distro_series_task.transitionToTarget(
... distro_series_task.target.distroseries, getUtility(ILaunchBag).user)
- >>> canonical_url(distro_series_task)
- u'http://bugs.launchpad.test/debian/sarge/+bug/3'
+ >>> print(canonical_url(distro_series_task))
+ http://bugs.launchpad.test/debian/sarge/+bug/3
>>> distro_series_task.transitionToTarget(
... temp_target, getUtility(ILaunchBag).user)
@@ -257,13 +257,13 @@ private.)
>>> login(ANONYMOUS)
- >>> canonical_url(distro_series_task.bug)
- u'http://bugs.launchpad.test/bugs/3'
+ >>> print(canonical_url(distro_series_task.bug))
+ http://bugs.launchpad.test/bugs/3
A private bugtask, as an anonymous user.
- >>> canonical_url(distro_series_task)
- u'http://bugs.launchpad.test/debian/sarge/+source/mozilla-firefox/+bug/3'
+ >>> print(canonical_url(distro_series_task))
+ http://bugs.launchpad.test/debian/sarge/+source/mozilla-firefox/+bug/3
>>> login("foo.bar@xxxxxxxxxxxxx")
>>> distro_series_task.bug.setPrivate(False, getUtility(ILaunchBag).user)
@@ -275,8 +275,8 @@ An IBugWatchSet.
This doesn't work, because BugWatchSet.bug is an int, not an IBug object.
xxx bug_one_watches = BugWatchSet(bug=1)
- xxx canonical_url(bug_one_watches)
- u'http://launchpad.test/bugs/1/watches'
+ xxx print(canonical_url(bug_one_watches))
+ http://launchpad.test/bugs/1/watches
An IBugComment.
@@ -285,15 +285,15 @@ An IBugComment.
>>> bugtask_one = bug_one.bugtasks[0]
>>> bug_comment = BugComment(
... 1, bug_one.initial_message, bugtask_one, True)
- >>> canonical_url(bug_comment)
- u'http://bugs.launchpad.test/firefox/+bug/1/comments/1'
+ >>> print(canonical_url(bug_comment))
+ http://bugs.launchpad.test/firefox/+bug/1/comments/1
An IBugNomination.
>>> from lp.bugs.interfaces.bugnomination import IBugNominationSet
>>> bug_nomination = getUtility(IBugNominationSet).get(1)
- >>> canonical_url(bug_nomination)
- u'http://bugs.launchpad.test/bugs/1/nominations/1'
+ >>> print(canonical_url(bug_nomination))
+ http://bugs.launchpad.test/bugs/1/nominations/1
Remote Bug Trackers and Remote Bugs
@@ -304,21 +304,21 @@ Remote Bug Trackers and Remote Bugs
An IBugTrackerSet.
- >>> canonical_url(getUtility(IBugTrackerSet))
- u'http://bugs.launchpad.test/bugs/bugtrackers'
+ >>> print(canonical_url(getUtility(IBugTrackerSet)))
+ http://bugs.launchpad.test/bugs/bugtrackers
A remote bug tracker.
>>> mozilla_bugtracker = getUtility(IBugTrackerSet)['mozilla.org']
- >>> canonical_url(mozilla_bugtracker)
- u'http://bugs.launchpad.test/bugs/bugtrackers/mozilla.org'
+ >>> print(canonical_url(mozilla_bugtracker))
+ http://bugs.launchpad.test/bugs/bugtrackers/mozilla.org
A bug from a remote bug tracker.
>>> remote_bug = RemoteBug(mozilla_bugtracker, '42',
... mozilla_bugtracker.getBugsWatching('42'))
- >>> canonical_url(remote_bug)
- u'http://bugs.launchpad.test/bugs/bugtrackers/mozilla.org/42'
+ >>> print(canonical_url(remote_bug))
+ http://bugs.launchpad.test/bugs/bugtrackers/mozilla.org/42
Branches
@@ -330,16 +330,16 @@ An IBranch.
>>> branch = getUtility(IBranchLookup).get(10)
- >>> canonical_url(branch)
- u'http://code.launchpad.test/~mark/firefox/release-0.9.2'
+ >>> print(canonical_url(branch))
+ http://code.launchpad.test/~mark/firefox/release-0.9.2
An IBugBranch.
>>> bug = getUtility(IBugSet).get(1)
>>> bug.linkBranch(branch, getUtility(IPersonSet).getByName('mark'))
>>> [bug_branch] = bug.linked_bugbranches
- >>> canonical_url(bug_branch)
- u'http://launchpad.test/~mark/firefox/release-0.9.2/+bug/1'
+ >>> print(canonical_url(bug_branch))
+ http://launchpad.test/~mark/firefox/release-0.9.2/+bug/1
BranchMergeProposals
@@ -385,8 +385,9 @@ Specifications
>>> from lp.blueprints.interfaces.specification import ISpecificationSet
>>> spec_set = getUtility(ISpecificationSet)
- >>> canonical_url(spec_set)
- u'http://blueprints.launchpad.test/'
+ >>> print(canonical_url(spec_set))
+ http://blueprints.launchpad.test/
- >>> canonical_url(celebs.ubuntu.getSpecification('media-integrity-check'))
- u'http://blueprints.launchpad.test/ubuntu/+spec/media-integrity-check'
+ >>> print(canonical_url(
+ ... celebs.ubuntu.getSpecification('media-integrity-check')))
+ http://blueprints.launchpad.test/ubuntu/+spec/media-integrity-check
diff --git a/lib/lp/services/webapp/doc/menus.txt b/lib/lp/services/webapp/doc/menus.txt
index 0803475..ada19bd 100644
--- a/lib/lp/services/webapp/doc/menus.txt
+++ b/lib/lp/services/webapp/doc/menus.txt
@@ -45,11 +45,11 @@ Let's make three objects that together make a url hierarchy:
>>> root = ExampleContentObject('', None)
>>> street = ExampleContentObject('sesamestreet', root)
>>> house = ExampleContentObject('number73', street)
- >>> canonical_url(house)
- u'http://launchpad.test/sesamestreet/number73'
+ >>> print(canonical_url(house))
+ http://launchpad.test/sesamestreet/number73
- >>> canonical_url(street)
- u'http://launchpad.test/sesamestreet'
+ >>> print(canonical_url(street))
+ http://launchpad.test/sesamestreet
== The Link class ==
@@ -303,20 +303,20 @@ Checking out the escapedtext attribute.
>>> link = Link('+target', 'text -->')
- >>> ILink(link).escapedtext
- u'text -->'
+ >>> print(ILink(link).escapedtext)
+ text -->
- >>> IFacetLink(link).escapedtext
- u'text -->'
+ >>> print(IFacetLink(link).escapedtext)
+ text -->
>>> text = structured('some <b> %s </b> text', '-->')
>>> link = Link('+target', text)
- >>> ILink(link).escapedtext
- u'some <b> --> </b> text'
+ >>> print(ILink(link).escapedtext)
+ some <b> --> </b> text
- >>> IFacetLink(link).escapedtext
- u'some <b> --> </b> text'
+ >>> print(IFacetLink(link).escapedtext)
+ some <b> --> </b> text
Next, we return the link as HTML.
diff --git a/lib/lp/services/webapp/doc/navigation.txt b/lib/lp/services/webapp/doc/navigation.txt
index 9abe14f..cd96dcf 100644
--- a/lib/lp/services/webapp/doc/navigation.txt
+++ b/lib/lp/services/webapp/doc/navigation.txt
@@ -455,37 +455,37 @@ Let's make another navigation class to test redirection.
>>> navigation4 = ThingSetNavigation4(thingset, request)
>>> navigation4.publishTraverse(request, 'tree')
<...RedirectionView...>
- >>> navigation4.publishTraverse(request, 'tree')()
- u''
+ >>> print(navigation4.publishTraverse(request, 'tree')())
+ <BLANKLINE>
>>> request.response.redirected_to
'trees'
>>> print request.response.status
301
- >>> navigation4.publishTraverse(request, 'toad')()
- u''
+ >>> print(navigation4.publishTraverse(request, 'toad')())
+ <BLANKLINE>
>>> request.response.redirected_to
'toads'
>>> print request.response.status
None
- >>> navigation4.publishTraverse(request, 'something')()
- u''
+ >>> print(navigation4.publishTraverse(request, 'something')())
+ <BLANKLINE>
>>> request.response.redirected_to
'/another/place'
>>> print request.response.status
301
>>> request.traversal_stack = ['tundra']
- >>> navigation4.publishTraverse(request, 'outerspace')()
- u''
+ >>> print(navigation4.publishTraverse(request, 'outerspace')())
+ <BLANKLINE>
>>> request.response.redirected_to
'/siberia/tundra'
>>> print request.response.status
None
- >>> navigation4.publishTraverse(request, 'here')()
- u''
+ >>> print(navigation4.publishTraverse(request, 'here')())
+ <BLANKLINE>
>>> request.response.redirected_to
'/there'
>>> print request.response.status
@@ -509,8 +509,8 @@ with the remainder of the URL and or query string.
>>> navigation5 = ThingSetNavigation5(thingset, request)
>>> navigation5.publishTraverse(request, 'jobs')
<...RedirectionView...>
- >>> navigation5.publishTraverse(request, 'jobs')()
- u''
+ >>> print(navigation5.publishTraverse(request, 'jobs')())
+ <BLANKLINE>
>>> request.response.redirected_to
'http://ubuntu.com/jobs'
>>> print request.response.status
@@ -518,8 +518,8 @@ with the remainder of the URL and or query string.
>>> request.traversal_stack = ['LaunchpadMeeting']
>>> request.query_string = 'hilight=Time'
- >>> navigation5.publishTraverse(request, '+foo')()
- u''
+ >>> print(navigation5.publishTraverse(request, '+foo')())
+ <BLANKLINE>
>>> request.response.redirected_to
'http://wiki.canonical.com/LaunchpadMeeting?hilight=Time'
>>> print request.response.status
@@ -575,8 +575,8 @@ Check out the traversals defined directly.
>>> ubernav.publishTraverse(request, 'diplodocus')
'diplodocus called frank'
- >>> ubernav.publishTraverse(request, 'topology')()
- u''
+ >>> print(ubernav.publishTraverse(request, 'topology')())
+ <BLANKLINE>
>>> request.response.redirected_to
'topologies'
@@ -600,18 +600,18 @@ Check those from ThingSetNavigation3:
Check those from ThingSetNavigation4:
- >>> ubernav.publishTraverse(request, 'tree')()
- u''
+ >>> print(ubernav.publishTraverse(request, 'tree')())
+ <BLANKLINE>
>>> request.response.redirected_to
'trees'
- >>> ubernav.publishTraverse(request, 'toad')()
- u''
+ >>> print(ubernav.publishTraverse(request, 'toad')())
+ <BLANKLINE>
>>> request.response.redirected_to
'toads'
- >>> ubernav.publishTraverse(request, 'ttt')()
- u''
+ >>> print(ubernav.publishTraverse(request, 'ttt')())
+ <BLANKLINE>
>>> request.response.redirected_to
'/another/place'
diff --git a/lib/lp/services/webapp/doc/notification-text-escape.txt b/lib/lp/services/webapp/doc/notification-text-escape.txt
index 01cab67..3275f9b 100644
--- a/lib/lp/services/webapp/doc/notification-text-escape.txt
+++ b/lib/lp/services/webapp/doc/notification-text-escape.txt
@@ -33,8 +33,8 @@ But text containing markup is CGI-escaped:
>>> response = new_response()
>>> response.addNotification(u'<br/>dirty')
>>> for notification in response.notifications:
- ... notification.message
- u'<br/>dirty'
+ ... print(notification.message)
+ <br/>dirty
If the object passed to addNotification() publishes the
@@ -47,14 +47,14 @@ appropriate sections escaped and unescaped.
>>> structured_text = structured(msg, escaped=u'<br/>foo')
>>> IStructuredString.providedBy(structured_text)
True
- >>> structured_text.escapedtext
- u'<b><br/>foo</b>'
+ >>> print(structured_text.escapedtext)
+ <b><br/>foo</b>
>>> response = new_response()
>>> response.addNotification(structured_text)
>>> for notification in response.notifications:
- ... notification.message
- u'<b><br/>foo</b>'
+ ... print(notification.message)
+ <b><br/>foo</b>
Passing an object to addNotification() that is an instance of
zope.i18n.Message will be escaped in the same
@@ -65,8 +65,8 @@ manner as raw text.
>>> response = new_response()
>>> response.addNotification(msgtxt)
>>> for notification in response.notifications:
- ... notification.message
- u'<br/>foo'
+ ... print(notification.message)
+ <br/>foo
To pass internationalized text that contains markup, one may call
structured() directly with an internationalized object. structured()
@@ -77,11 +77,11 @@ may then be passed to addNotification().
>>> msgid = _(u'<good/>%(evil)s')
>>> escapee = '<evil/>'
>>> text = structured(msgid, evil=escapee)
- >>> text.escapedtext
- u'<good/><evil/>'
+ >>> print(text.escapedtext)
+ <good/><evil/>
>>> response = new_response()
>>> response.addNotification(text)
>>> for notification in response.notifications:
- ... notification.message
- u'<good/><evil/>'
+ ... print(notification.message)
+ <good/><evil/>
diff --git a/lib/lp/services/webapp/doc/renamed-view.txt b/lib/lp/services/webapp/doc/renamed-view.txt
index fafb350..2a8fd70 100644
--- a/lib/lp/services/webapp/doc/renamed-view.txt
+++ b/lib/lp/services/webapp/doc/renamed-view.txt
@@ -29,8 +29,8 @@ the new name. The redirection status is 301 (Moved permently) which
will make search engines discards the old URLs and some browser to
update bookmarks.
- >>> view()
- u''
+ >>> print(view())
+ <BLANKLINE>
>>> request.response.getStatus()
301
>>> print request.response.getHeader('Location')
@@ -42,8 +42,8 @@ new_name can be a relative path.
>>> from lp.services.webapp.interfaces import ILaunchpadRoot
>>> root = getUtility(ILaunchpadRoot)
>>> view = RenamedView(root, LaunchpadTestRequest(), '+tour/index.html')
- >>> view()
- u''
+ >>> print(view())
+ <BLANKLINE>
>>> request.response.getStatus()
301
>>> print view.request.response.getHeader('Location')
@@ -58,8 +58,8 @@ to the redirected URL.
>>> request = LaunchpadTestRequest(
... QUERY_STRING='field.status=Open')
>>> view = RenamedView(ubuntu, request, '+questions')
- >>> view()
- u''
+ >>> print(view())
+ <BLANKLINE>
>>> print request.response.getHeader('Location')
http://launchpad.test/ubuntu/+questions?field.status=Open
@@ -72,8 +72,8 @@ change the virtual host used for the redirection.
>>> request = LaunchpadTestRequest()
>>> view = RenamedView(
... ubuntu, request, '+questions', rootsite='answers')
- >>> view()
- u''
+ >>> print(view())
+ <BLANKLINE>
>>> print request.response.getHeader('Location')
http://answers.launchpad.test/ubuntu/+questions
@@ -115,7 +115,7 @@ browser:renamed-page is available for this purpose.
>>> from zope.component import getMultiAdapter
>>> request = LaunchpadTestRequest()
>>> view = getMultiAdapter((ubuntu, request), name='+old_tickets_page')
- >>> view()
- u''
+ >>> print(view())
+ <BLANKLINE>
>>> print request.response.getHeader('Location')
http://answers.launchpad.test/ubuntu/+questions
diff --git a/lib/lp/services/webapp/doc/test_adapter.txt b/lib/lp/services/webapp/doc/test_adapter.txt
index 2cb559d..d91cfb2 100644
--- a/lib/lp/services/webapp/doc/test_adapter.txt
+++ b/lib/lp/services/webapp/doc/test_adapter.txt
@@ -351,8 +351,8 @@ The statement about to be executed is not recorded in the statement log.
The request time limit was exceeded before the statement was issued to
the database.
- >>> get_request_statements()
- [(0, ..., u'SQL-main-master', u'SELECT 2', ...)]
+ >>> print(pretty(get_request_statements()))
+ [(0, ..., 'SQL-main-master', 'SELECT 2', ...)]
When a RequestExpired exception is raised, the current
diff --git a/lib/lp/services/webapp/doc/test_adapter_permissions.txt b/lib/lp/services/webapp/doc/test_adapter_permissions.txt
index aaf56ec..17423b5 100644
--- a/lib/lp/services/webapp/doc/test_adapter_permissions.txt
+++ b/lib/lp/services/webapp/doc/test_adapter_permissions.txt
@@ -43,6 +43,6 @@ Store's replication set.
>>> main_master.find(Person, name='janitor').one().display_name = 'BenD'
>>> transaction.commit()
>>> t = transaction.begin()
- >>> main_master.find(Person, name='janitor').one().display_name
- u'BenD'
+ >>> print(main_master.find(Person, name='janitor').one().display_name)
+ BenD
>>> transaction.abort()
diff --git a/lib/lp/services/webapp/doc/webapp-publication.txt b/lib/lp/services/webapp/doc/webapp-publication.txt
index 7329dbb..fa178cd 100644
--- a/lib/lp/services/webapp/doc/webapp-publication.txt
+++ b/lib/lp/services/webapp/doc/webapp-publication.txt
@@ -526,8 +526,8 @@ The advantage of the IBrowserFormNG API is that it offers methods that
checks the number of values you are expecting. The getOne() method
should be used when you expect only one value for the field.
- >>> request.form_ng.getOne('a_field')
- u'a_value'
+ >>> print(request.form_ng.getOne('a_field'))
+ a_value
UnexpectedFormData is raised if more than one value was submitted for
the field:
@@ -546,20 +546,24 @@ None is returned if the field wasn't submitted:
You can provide a default value that is returned if the field wasn't
submitted:
- >>> request.form_ng.getOne('another_field', u'default')
- u'default'
+ >>> print(request.form_ng.getOne('another_field', u'default'))
+ default
The getAll() method should be used when you are expecting a list of
values.
- >>> request.form_ng.getAll('items_field')
- [u'1', u'2', u'3']
+ >>> for item in request.form_ng.getAll('items_field'):
+ ... print(item)
+ 1
+ 2
+ 3
If only one value was submitted, it will still be returned as part of
a list:
- >>> request.form_ng.getAll('a_field')
- [u'a_value']
+ >>> for item in request.form_ng.getAll('a_field'):
+ ... print(item)
+ a_value
An empty list is returned when no value was submitted for the field:
@@ -569,8 +573,9 @@ An empty list is returned when no value was submitted for the field:
That method also accepts a default value that is to be returned when
no value was submitted with the field.
- >>> request.form_ng.getAll('another_field', [u'default'])
- [u'default']
+ >>> for item in request.form_ng.getAll('another_field', [u'default']):
+ ... print(item)
+ default
All the submitted field names can be iterated over:
@@ -666,8 +671,9 @@ current thread.
False
>>> 'launchpad.publicationthreadduration' in request._orig_env
False
- >>> publication.callObject(request, TestView(TestContext(), request))
- u'Result'
+ >>> print(publication.callObject(
+ ... request, TestView(TestContext(), request)))
+ Result
>>> publication.afterCall(request, None)
>>> 'launchpad.publicationduration' in request._orig_env
True
@@ -732,8 +738,9 @@ completed), we'll have the duration for the traversal and the duration for
the publication, up to the point where it was forcefully stopped.
>>> publication.afterTraversal(request, None)
- >>> publication.callObject(request, TestView(TestContext(), request))
- u'Result'
+ >>> print(publication.callObject(
+ ... request, TestView(TestContext(), request)))
+ Result
>>> set_request_started()
>>> publication.handleException(
... None, request, exc_info, retry_allowed=False)
@@ -1149,8 +1156,8 @@ token.
Guilherme Salgado
>>> principal.access_level
<DBItem AccessLevel.WRITE_PUBLIC...
- >>> principal.scope_url
- u'/firefox'
+ >>> print(principal.scope_url)
+ /firefox
If the token is expired or doesn't exist, an Unauthorized exception is
raised, though.
diff --git a/lib/lp/services/webapp/doc/zcmldirectives.txt b/lib/lp/services/webapp/doc/zcmldirectives.txt
index 0652b1a..71b14e4 100644
--- a/lib/lp/services/webapp/doc/zcmldirectives.txt
+++ b/lib/lp/services/webapp/doc/zcmldirectives.txt
@@ -302,8 +302,8 @@ an IPermission.
>>> permission = getUtility(ILaunchpadPermission, 'foo.bar')
>>> verifyObject(ILaunchpadPermission, permission)
True
- >>> permission.access_level
- u'read'
+ >>> print(permission.access_level)
+ read
== Cleaning up the interfaces and objects to test with ==
diff --git a/lib/lp/services/webapp/notifications.py b/lib/lp/services/webapp/notifications.py
index a0fb1c2..151ab02 100644
--- a/lib/lp/services/webapp/notifications.py
+++ b/lib/lp/services/webapp/notifications.py
@@ -60,8 +60,9 @@ class NotificationRequest:
>>> notifications = NotificationList()
>>> session['notifications'] = notifications
>>> notifications.append(Notification(0, 'Fnord'))
- >>> [notification.message for notification in request.notifications]
- ['Fnord']
+ >>> for notification in request.notifications:
+ ... print(notification.message)
+ Fnord
Note that NotificationRequest.notifications also returns any notifications
that have been added so far in this request, making it the single source
@@ -69,8 +70,10 @@ class NotificationRequest:
>>> response = INotificationResponse(request)
>>> response.addNotification('Aargh')
- >>> [notification.message for notification in request.notifications]
- ['Fnord', u'Aargh']
+ >>> for notification in request.notifications:
+ ... print(notification.message)
+ Fnord
+ Aargh
"""
@property
@@ -263,17 +266,17 @@ class NotificationList(list):
>>> notifications.append(Notification(error, u'An error'))
>>> notifications.append(Notification(debug, u'A debug message'))
>>> for notification in notifications:
- ... print(repr(notification.message))
- u'An error'
- u'A debug message'
+ ... print(notification.message)
+ An error
+ A debug message
The __getitem__ method is also overloaded to allow TALES expressions
to easily retrieve lists of notifications that match a particular
notification level.
>>> for notification in notifications['debug']:
- ... print(repr(notification.message))
- u'A debug message'
+ ... print(notification.message)
+ A debug message
"""
created = None
diff --git a/lib/lp/services/webapp/servers.py b/lib/lp/services/webapp/servers.py
index 0e2bf17..49ac4dd 100644
--- a/lib/lp/services/webapp/servers.py
+++ b/lib/lp/services/webapp/servers.py
@@ -1018,8 +1018,8 @@ class LaunchpadTestResponse(LaunchpadBrowserResponse):
True
>>> response.addWarningNotification('Warning Notification')
- >>> request.notifications[0].message
- u'Warning Notification'
+ >>> print(request.notifications[0].message)
+ Warning Notification
"""
uuid = 'LaunchpadTestResponse'
diff --git a/lib/lp/services/webapp/tests/test_doc.py b/lib/lp/services/webapp/tests/test_doc.py
index fab33d6..7af6c91 100644
--- a/lib/lp/services/webapp/tests/test_doc.py
+++ b/lib/lp/services/webapp/tests/test_doc.py
@@ -17,6 +17,7 @@ from lp.testing.layers import (
)
from lp.testing.systemdocs import (
LayeredDocFileSuite,
+ setGlobs,
setUp,
tearDown,
)
@@ -37,7 +38,7 @@ special = {
stdout_logging=False, layer=None),
'test_adapter.txt': LayeredDocFileSuite(
'../doc/test_adapter.txt',
- layer=LaunchpadFunctionalLayer),
+ setUp=setGlobs, layer=LaunchpadFunctionalLayer),
# XXX Julian 2009-05-13, bug=376171
# Temporarily disabled because of intermittent failures.
# 'test_adapter_timeout.txt': LayeredDocFileSuite(
diff --git a/lib/lp/services/webservice/doc/webservice-marshallers.txt b/lib/lp/services/webservice/doc/webservice-marshallers.txt
index 17cfa94..2b4504d 100644
--- a/lib/lp/services/webservice/doc/webservice-marshallers.txt
+++ b/lib/lp/services/webservice/doc/webservice-marshallers.txt
@@ -52,13 +52,13 @@ returns that item. Otherwise it raises a ValueError.
... "http://api.launchpad.test/beta/~salgado")
>>> IPerson.providedBy(person)
True
- >>> person.name
- u'salgado'
+ >>> print(person.name)
+ salgado
>>> ubuntu_team = marshaller.marshall_from_json_data(
... "http://api.launchpad.test/beta/~ubuntu-team")
- >>> ubuntu_team.name
- u'ubuntu-team'
+ >>> print(ubuntu_team.name)
+ ubuntu-team
>>> marshaller.marshall_from_request(
... "http://api.launchpad.test/beta/~nosuchperson")
@@ -77,8 +77,8 @@ the URL to that object.
>>> person_resource = EntryResource(person, request)
- >>> marshaller.unmarshall(person_resource, person)
- u'http://.../~salgado'
+ >>> print(marshaller.unmarshall(person_resource, person))
+ http://.../~salgado
This marshaller also appends '_link' to the representation name of
this field, so that clients can know this is a link to another
diff --git a/lib/lp/services/webservice/stories/datamodel.txt b/lib/lp/services/webservice/stories/datamodel.txt
index f47d6c3..5ca2388 100644
--- a/lib/lp/services/webservice/stories/datamodel.txt
+++ b/lib/lp/services/webservice/stories/datamodel.txt
@@ -19,8 +19,12 @@ Normally, the total size of a collection is not served along with the
collection; it's available by following the total_size_link.
>>> collection = get_collection()
- >>> print(sorted(collection.keys()))
- [u'entries', u'next_collection_link', u'start', u'total_size_link']
+ >>> for key in sorted(collection.keys()):
+ ... print(key)
+ entries
+ next_collection_link
+ start
+ total_size_link
>>> print(webservice.get(collection['total_size_link']).jsonBody())
9
@@ -29,8 +33,11 @@ collection obvious), 'total_size' is served instead of
'total_size_link'.
>>> collection = get_collection(size=100)
- >>> print(sorted(collection.keys()))
- [u'entries', u'start', u'total_size']
+ >>> for key in sorted(collection.keys()):
+ ... print(key)
+ entries
+ start
+ total_size
>>> print(collection['total_size'])
9
@@ -39,7 +46,11 @@ of the collection semi-obvious), 'total_size' is served instead of
'total_size_link'.
>>> collection = get_collection(start=8)
- >>> print(sorted(collection.keys()))
- [u'entries', u'prev_collection_link', u'start', u'total_size']
+ >>> for key in sorted(collection.keys()):
+ ... print(key)
+ entries
+ prev_collection_link
+ start
+ total_size
>>> print(collection['total_size'])
9
diff --git a/lib/lp/services/webservice/stories/multiversion.txt b/lib/lp/services/webservice/stories/multiversion.txt
index bc4f855..22f9722 100644
--- a/lib/lp/services/webservice/stories/multiversion.txt
+++ b/lib/lp/services/webservice/stories/multiversion.txt
@@ -17,8 +17,12 @@ total size of the collection.
... return collection.jsonBody()
>>> collection = get_collection("devel")
- >>> print(sorted(collection.keys()))
- [u'entries', u'next_collection_link', u'start', u'total_size_link']
+ >>> for key in sorted(collection.keys()):
+ ... print(key)
+ entries
+ next_collection_link
+ start
+ total_size_link
>>> print(webservice.get(collection['total_size_link']).jsonBody())
9
@@ -26,8 +30,12 @@ In previous versions, the same named operations will return a
'total_size' containing the actual size of the collection.
>>> collection = get_collection("1.0")
- >>> print(sorted(collection.keys()))
- [u'entries', u'next_collection_link', u'start', u'total_size']
+ >>> for key in sorted(collection.keys()):
+ ... print(key)
+ entries
+ next_collection_link
+ start
+ total_size
>>> print(collection['total_size'])
9
diff --git a/lib/lp/services/webservice/stories/xx-hostedfile.txt b/lib/lp/services/webservice/stories/xx-hostedfile.txt
index bda79d6..a318435 100644
--- a/lib/lp/services/webservice/stories/xx-hostedfile.txt
+++ b/lib/lp/services/webservice/stories/xx-hostedfile.txt
@@ -12,12 +12,12 @@ The librarian manages hosted files
Firefox starts out with a link to branding images, but no actual images.
>>> project = webservice.get('/firefox').jsonBody()
- >>> project['icon_link']
- u'http://.../firefox/icon'
- >>> project['logo_link']
- u'http://.../firefox/logo'
- >>> project['brand_link']
- u'http://.../firefox/brand'
+ >>> print(project['icon_link'])
+ http://.../firefox/icon
+ >>> print(project['logo_link'])
+ http://.../firefox/logo
+ >>> print(project['brand_link'])
+ http://.../firefox/brand
>>> print(webservice.get(project['icon_link']))
HTTP/1.1 404 Not Found
diff --git a/lib/lp/services/webservice/stories/xx-wadl.txt b/lib/lp/services/webservice/stories/xx-wadl.txt
index f7180ef..70e1dcf 100644
--- a/lib/lp/services/webservice/stories/xx-wadl.txt
+++ b/lib/lp/services/webservice/stories/xx-wadl.txt
@@ -39,8 +39,8 @@ from disk.
The fake WADL is now present in the cache.
- >>> WebServiceApplication.cached_wadl
- {u'devel': u'Some fake WADL.'}
+ >>> print(pretty(WebServiceApplication.cached_wadl))
+ {'devel': 'Some fake WADL.'}
Change the cached value, and we change the document served.
@@ -91,8 +91,10 @@ we'll get a document keyed to the '1.0' version.
All of these documents were cached as they were generated:
- >>> sorted(WebServiceApplication.cached_wadl.keys())
- [u'1.0', u'devel']
+ >>> for key in sorted(WebServiceApplication.cached_wadl.keys()):
+ ... print(key)
+ 1.0
+ devel
Finally, restore the cache so that other tests will have a clean
slate.
diff --git a/lib/lp/services/worlddata/doc/language.txt b/lib/lp/services/worlddata/doc/language.txt
index 62feb61..b5e5c0c 100644
--- a/lib/lp/services/worlddata/doc/language.txt
+++ b/lib/lp/services/worlddata/doc/language.txt
@@ -11,8 +11,8 @@ getLanguageByCode
We can get hold of languages by their language code.
>>> language = language_set.getLanguageByCode('es')
- >>> language.englishname
- u'Spanish'
+ >>> print(language.englishname)
+ Spanish
Or if it doesn't exist, we return None.
@@ -273,11 +273,28 @@ Property holding a list of countries a language is spoken in, and allowing
reading and setting them.
>>> es = language_set.getLanguageByCode('es')
- >>> print([country.name for country in es.countries])
- [u'Argentina', u'Bolivia', u'Chile', u'Colombia', u'Costa Rica',
- u'Dominican Republic', u'Ecuador', u'El Salvador', u'Guatemala',
- u'Honduras', u'Mexico', u'Nicaragua', u'Panama', u'Paraguay', u'Peru',
- u'Puerto Rico', u'Spain', u'United States', u'Uruguay', u'Venezuela']
+ >>> for country in es.countries:
+ ... print(country.name)
+ Argentina
+ Bolivia
+ Chile
+ Colombia
+ Costa Rica
+ Dominican Republic
+ Ecuador
+ El Salvador
+ Guatemala
+ Honduras
+ Mexico
+ Nicaragua
+ Panama
+ Paraguay
+ Peru
+ Puerto Rico
+ Spain
+ United States
+ Uruguay
+ Venezuela
We can add countries using `ILanguage.addCountry` method.
@@ -285,26 +302,63 @@ We can add countries using `ILanguage.addCountry` method.
>>> country_set = getUtility(ICountrySet)
>>> germany = country_set['DE']
>>> es.addCountry(germany)
- >>> print([country.name for country in es.countries])
- [u'Argentina', u'Bolivia', u'Chile', u'Colombia', u'Costa Rica',
- u'Dominican Republic', u'Ecuador', u'El Salvador', u'Germany', u'Guatemala',
- u'Honduras', u'Mexico', u'Nicaragua', u'Panama', u'Paraguay', u'Peru',
- u'Puerto Rico', u'Spain', u'United States', u'Uruguay', u'Venezuela']
+ >>> for country in es.countries:
+ ... print(country.name)
+ Argentina
+ Bolivia
+ Chile
+ Colombia
+ Costa Rica
+ Dominican Republic
+ Ecuador
+ El Salvador
+ Germany
+ Guatemala
+ Honduras
+ Mexico
+ Nicaragua
+ Panama
+ Paraguay
+ Peru
+ Puerto Rico
+ Spain
+ United States
+ Uruguay
+ Venezuela
Or, we can remove countries using `ILanguage.removeCountry` method.
>>> argentina = country_set['AR']
>>> es.removeCountry(argentina)
- >>> print([country.name for country in es.countries])
- [u'Bolivia', u'Chile', u'Colombia', u'Costa Rica', u'Dominican Republic',
- u'Ecuador', u'El Salvador', u'Germany', u'Guatemala', u'Honduras',
- u'Mexico', u'Nicaragua', u'Panama', u'Paraguay', u'Peru', u'Puerto Rico',
- u'Spain', u'United States', u'Uruguay', u'Venezuela']
+ >>> for country in es.countries:
+ ... print(country.name)
+ Bolivia
+ Chile
+ Colombia
+ Costa Rica
+ Dominican Republic
+ Ecuador
+ El Salvador
+ Germany
+ Guatemala
+ Honduras
+ Mexico
+ Nicaragua
+ Panama
+ Paraguay
+ Peru
+ Puerto Rico
+ Spain
+ United States
+ Uruguay
+ Venezuela
We can also assign a complete set of languages directly to `countries`,
but we need to log in as a translations administrator first.
>>> login('carlos@xxxxxxxxxxxxx')
>>> es.countries = set([argentina, germany])
- >>> print([country.name for country in es.countries])
- [u'Argentina', u'Germany']
+ >>> for country in es.countries:
+ ... print(country.name)
+ Argentina
+ Germany
diff --git a/lib/lp/services/worlddata/doc/vocabularies.txt b/lib/lp/services/worlddata/doc/vocabularies.txt
index ab100ea..6b91d7a 100644
--- a/lib/lp/services/worlddata/doc/vocabularies.txt
+++ b/lib/lp/services/worlddata/doc/vocabularies.txt
@@ -131,8 +131,10 @@ excluded from the vocabulary.
>>> len(hidden_languages)
89
- >>> [lang.displayname for lang in difference if lang.visible]
- [u'English (en)']
+ >>> for lang in difference:
+ ... if lang.visible:
+ ... print(lang.displayname)
+ English (en)
The vocabulary will raise a LookupError if asked to return English.
diff --git a/lib/lp/services/worlddata/stories/webservice/xx-language.txt b/lib/lp/services/worlddata/stories/webservice/xx-language.txt
index 56484ae..baa37c9 100644
--- a/lib/lp/services/worlddata/stories/webservice/xx-language.txt
+++ b/lib/lp/services/worlddata/stories/webservice/xx-language.txt
@@ -8,8 +8,8 @@ The language information from Launchpad can be queried using
'/+languages/CC', where CC is the language code.
>>> es = anon_webservice.get('/+languages/es').jsonBody()
- >>> es['resource_type_link']
- u'http.../#language'
+ >>> print(es['resource_type_link'])
+ http.../#language
>>> print(es['text_direction'])
Left to Right
>>> print(es['code'])
@@ -42,8 +42,8 @@ at '/+languages'.
... list += language['english_name'] + '(hidden)' + "\n"
... return list
>>> default_languages = anon_webservice.get('/+languages').jsonBody()
- >>> default_languages['resource_type_link']
- u'http.../#languages'
+ >>> print(default_languages['resource_type_link'])
+ http.../#languages
>>> languages = get_languages_entries(default_languages)
>>> print(languages)
Abkhazian