launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #26519
[Merge] ~cjwatson/launchpad:py3-bug-export into launchpad:master
Colin Watson has proposed merging ~cjwatson/launchpad:py3-bug-export into launchpad:master.
Commit message:
Port bug-export.py to Python 3
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/399018
We need to use io.BytesIO, adjust for Python 3's base64 and xml.etree.ElementTree changes, and use sys.stdout.buffer where appropriate.
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:py3-bug-export into launchpad:master.
diff --git a/lib/lp/bugs/doc/bug-export.txt b/lib/lp/bugs/doc/bug-export.txt
index 3df8a3b..b0736e2 100644
--- a/lib/lp/bugs/doc/bug-export.txt
+++ b/lib/lp/bugs/doc/bug-export.txt
@@ -19,13 +19,13 @@ Exporting one bug
We will export bug #1 in the context of Firefox. First some initial
setup:
+ >>> import io
>>> import sys
>>> try:
... import xml.etree.cElementTree as ET
... except ImportError:
... import cElementTree as ET
>>> from zope.component import getUtility
- >>> from cStringIO import StringIO
>>> from lp.bugs.interfaces.bug import IBugSet
>>> from lp.registry.interfaces.person import IPersonSet
>>> from lp.registry.interfaces.product import IProductSet
@@ -44,7 +44,9 @@ Now we serialise it as XML, and print it:
>>> node = serialise_bugtask(bugtask)
>>> tree = ET.ElementTree(node)
- >>> tree.write(sys.stdout)
+ >>> output = io.BytesIO()
+ >>> tree.write(output)
+ >>> print(output.getvalue().decode('UTF-8'))
<bug id="1">
<private>False</private>
<security_related>False</security_related>
@@ -93,7 +95,8 @@ bugs for a product. The export_bugtasks() function does this by
successively serialising each of the tasks for that product.
>>> import transaction
- >>> export_bugtasks(transaction, firefox, sys.stdout)
+ >>> export_bugtasks(
+ ... transaction, firefox, getattr(sys.stdout, 'buffer', sys.stdout))
<launchpad-bugs xmlns="https://launchpad.net/xmlns/2006/bugs">
<bug id="1">
...
@@ -131,13 +134,11 @@ Attachments are included in the XML dump. First add an attachment to
bug #1. We need to commit here so that the librarian can later serve
the file when we later serialise the bug:
- >>> from io import BytesIO
-
>>> login('test@xxxxxxxxxxxxx')
>>> bug4 = getUtility(IBugSet).get(4)
>>> sampleperson = getUtility(IPersonSet).getByEmail('test@xxxxxxxxxxxxx')
>>> bug4.addAttachment(
- ... sampleperson, BytesIO(b'Hello World'), 'Added attachment',
+ ... sampleperson, io.BytesIO(b'Hello World'), 'Added attachment',
... 'hello.txt', description='"Hello World" attachment')
<BugAttachment ...>
@@ -181,14 +182,14 @@ script. To test this, we'll make a bug private:
Now we'll do a dump not including private bugs:
- >>> output = StringIO()
+ >>> output = io.BytesIO()
>>> export_bugtasks(transaction, firefox, output)
- >>> '<bug id="4">' in output.getvalue()
+ >>> b'<bug id="4">' in output.getvalue()
False
However, bug #4 will appear in the export if we include private bugs:
- >>> output = StringIO()
+ >>> output = io.BytesIO()
>>> export_bugtasks(transaction, firefox, output, include_private=True)
- >>> '<bug id="4">' in output.getvalue()
+ >>> b'<bug id="4">' in output.getvalue()
True
diff --git a/lib/lp/bugs/scripts/bugexport.py b/lib/lp/bugs/scripts/bugexport.py
index 34873f1..de9fb66 100644
--- a/lib/lp/bugs/scripts/bugexport.py
+++ b/lib/lp/bugs/scripts/bugexport.py
@@ -8,7 +8,7 @@ __all__ = [
]
import base64
-
+import sys
try:
import xml.etree.cElementTree as ET
@@ -16,15 +16,23 @@ except ImportError:
import cElementTree as ET
from zope.component import getUtility
+
from lp.app.interfaces.launchpad import ILaunchpadCelebrities
-from lp.services.librarian.browser import ProxiedLibraryFileAlias
+from lp.bugs.browser.bugtask import get_comments_for_bugtask
from lp.bugs.interfaces.bugtask import IBugTaskSet
from lp.bugs.interfaces.bugtasksearch import BugTaskSearchParams
-from lp.bugs.browser.bugtask import get_comments_for_bugtask
+from lp.services.librarian.browser import ProxiedLibraryFileAlias
+
BUGS_XMLNS = 'https://launchpad.net/xmlns/2006/bugs'
+if sys.version_info[0] >= 3:
+ encodebytes = base64.encodebytes
+else:
+ encodebytes = base64.encodestring
+
+
def addnode(parent, elementname, content, **attrs):
node = ET.SubElement(parent, elementname, attrs)
node.text = content
@@ -95,7 +103,7 @@ def serialise_bugtask(bugtask):
attachment.libraryfile.mimetype)
# Attach the attachment file contents, base 64 encoded.
addnode(attachment_node, 'contents',
- base64.encodestring(attachment.libraryfile.read()))
+ encodebytes(attachment.libraryfile.read()).decode('ASCII'))
return bug_node
@@ -110,13 +118,14 @@ def export_bugtasks(ztm, bugtarget, output, include_private=False):
ids = [task.id for task in bugtarget.searchTasks(
BugTaskSearchParams(user=user, omit_dupes=False, orderby='id'))]
bugtaskset = getUtility(IBugTaskSet)
- output.write('<launchpad-bugs xmlns="%s">\n' % BUGS_XMLNS)
+ output.write(
+ ('<launchpad-bugs xmlns="%s">\n' % BUGS_XMLNS).encode('UTF-8'))
for count, taskid in enumerate(ids):
task = bugtaskset.get(taskid)
tree = ET.ElementTree(serialise_bugtask(task))
- tree.write(output)
+ tree.write(output, encoding="UTF-8", xml_declaration=False)
# Periodically abort the transaction so that we don't lock
# everyone else out.
if count % 100:
ztm.abort()
- output.write('</launchpad-bugs>\n')
+ output.write(b'</launchpad-bugs>\n')
diff --git a/scripts/bug-export.py b/scripts/bug-export.py
index b06daba..15bf58e 100755
--- a/scripts/bug-export.py
+++ b/scripts/bug-export.py
@@ -33,9 +33,10 @@ class BugExportScript(LaunchpadScript):
def main(self):
if self.options.product is None:
self.parser.error('No product specified')
- output = sys.stdout
if self.options.output is not None:
output = open(self.options.output, 'wb')
+ else:
+ output = getattr(sys.stdout, 'buffer', sys.stdout)
product = getUtility(IProductSet).getByName(self.options.product)
if product is None: