Merge ~cjwatson/launchpad:py3-bug-export into launchpad:master

Proposed by Colin Watson
Status: Merged
Approved by: Colin Watson
Approved revision: 9123e73adc021d8295694e5528b72c4b07465c13
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~cjwatson/launchpad:py3-bug-export
Merge into: launchpad:master
Diff against target: 156 lines (+29/-18)
3 files modified
lib/lp/bugs/doc/bug-export.txt (+11/-10)
lib/lp/bugs/scripts/bugexport.py (+16/-7)
scripts/bug-export.py (+2/-1)
Reviewer Review Type Date Requested Status
Cristian Gonzalez (community) Approve
Review via email: mp+399018@code.launchpad.net

Commit message

Port bug-export.py to Python 3

Description of the change

We need to use io.BytesIO, adjust for Python 3's base64 and xml.etree.ElementTree changes, and use sys.stdout.buffer where appropriate.

To post a comment you must log in.
Revision history for this message
Cristian Gonzalez (cristiangsp) wrote :

Looks good!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/lib/lp/bugs/doc/bug-export.txt b/lib/lp/bugs/doc/bug-export.txt
2index 3df8a3b..b0736e2 100644
3--- a/lib/lp/bugs/doc/bug-export.txt
4+++ b/lib/lp/bugs/doc/bug-export.txt
5@@ -19,13 +19,13 @@ Exporting one bug
6 We will export bug #1 in the context of Firefox. First some initial
7 setup:
8
9+ >>> import io
10 >>> import sys
11 >>> try:
12 ... import xml.etree.cElementTree as ET
13 ... except ImportError:
14 ... import cElementTree as ET
15 >>> from zope.component import getUtility
16- >>> from cStringIO import StringIO
17 >>> from lp.bugs.interfaces.bug import IBugSet
18 >>> from lp.registry.interfaces.person import IPersonSet
19 >>> from lp.registry.interfaces.product import IProductSet
20@@ -44,7 +44,9 @@ Now we serialise it as XML, and print it:
21
22 >>> node = serialise_bugtask(bugtask)
23 >>> tree = ET.ElementTree(node)
24- >>> tree.write(sys.stdout)
25+ >>> output = io.BytesIO()
26+ >>> tree.write(output)
27+ >>> print(output.getvalue().decode('UTF-8'))
28 <bug id="1">
29 <private>False</private>
30 <security_related>False</security_related>
31@@ -93,7 +95,8 @@ bugs for a product. The export_bugtasks() function does this by
32 successively serialising each of the tasks for that product.
33
34 >>> import transaction
35- >>> export_bugtasks(transaction, firefox, sys.stdout)
36+ >>> export_bugtasks(
37+ ... transaction, firefox, getattr(sys.stdout, 'buffer', sys.stdout))
38 <launchpad-bugs xmlns="https://launchpad.net/xmlns/2006/bugs">
39 <bug id="1">
40 ...
41@@ -131,13 +134,11 @@ Attachments are included in the XML dump. First add an attachment to
42 bug #1. We need to commit here so that the librarian can later serve
43 the file when we later serialise the bug:
44
45- >>> from io import BytesIO
46-
47 >>> login('test@canonical.com')
48 >>> bug4 = getUtility(IBugSet).get(4)
49 >>> sampleperson = getUtility(IPersonSet).getByEmail('test@canonical.com')
50 >>> bug4.addAttachment(
51- ... sampleperson, BytesIO(b'Hello World'), 'Added attachment',
52+ ... sampleperson, io.BytesIO(b'Hello World'), 'Added attachment',
53 ... 'hello.txt', description='"Hello World" attachment')
54 <BugAttachment ...>
55
56@@ -181,14 +182,14 @@ script. To test this, we'll make a bug private:
57
58 Now we'll do a dump not including private bugs:
59
60- >>> output = StringIO()
61+ >>> output = io.BytesIO()
62 >>> export_bugtasks(transaction, firefox, output)
63- >>> '<bug id="4">' in output.getvalue()
64+ >>> b'<bug id="4">' in output.getvalue()
65 False
66
67 However, bug #4 will appear in the export if we include private bugs:
68
69- >>> output = StringIO()
70+ >>> output = io.BytesIO()
71 >>> export_bugtasks(transaction, firefox, output, include_private=True)
72- >>> '<bug id="4">' in output.getvalue()
73+ >>> b'<bug id="4">' in output.getvalue()
74 True
75diff --git a/lib/lp/bugs/scripts/bugexport.py b/lib/lp/bugs/scripts/bugexport.py
76index 34873f1..de9fb66 100644
77--- a/lib/lp/bugs/scripts/bugexport.py
78+++ b/lib/lp/bugs/scripts/bugexport.py
79@@ -8,7 +8,7 @@ __all__ = [
80 ]
81
82 import base64
83-
84+import sys
85
86 try:
87 import xml.etree.cElementTree as ET
88@@ -16,15 +16,23 @@ except ImportError:
89 import cElementTree as ET
90
91 from zope.component import getUtility
92+
93 from lp.app.interfaces.launchpad import ILaunchpadCelebrities
94-from lp.services.librarian.browser import ProxiedLibraryFileAlias
95+from lp.bugs.browser.bugtask import get_comments_for_bugtask
96 from lp.bugs.interfaces.bugtask import IBugTaskSet
97 from lp.bugs.interfaces.bugtasksearch import BugTaskSearchParams
98-from lp.bugs.browser.bugtask import get_comments_for_bugtask
99+from lp.services.librarian.browser import ProxiedLibraryFileAlias
100+
101
102 BUGS_XMLNS = 'https://launchpad.net/xmlns/2006/bugs'
103
104
105+if sys.version_info[0] >= 3:
106+ encodebytes = base64.encodebytes
107+else:
108+ encodebytes = base64.encodestring
109+
110+
111 def addnode(parent, elementname, content, **attrs):
112 node = ET.SubElement(parent, elementname, attrs)
113 node.text = content
114@@ -95,7 +103,7 @@ def serialise_bugtask(bugtask):
115 attachment.libraryfile.mimetype)
116 # Attach the attachment file contents, base 64 encoded.
117 addnode(attachment_node, 'contents',
118- base64.encodestring(attachment.libraryfile.read()))
119+ encodebytes(attachment.libraryfile.read()).decode('ASCII'))
120
121 return bug_node
122
123@@ -110,13 +118,14 @@ def export_bugtasks(ztm, bugtarget, output, include_private=False):
124 ids = [task.id for task in bugtarget.searchTasks(
125 BugTaskSearchParams(user=user, omit_dupes=False, orderby='id'))]
126 bugtaskset = getUtility(IBugTaskSet)
127- output.write('<launchpad-bugs xmlns="%s">\n' % BUGS_XMLNS)
128+ output.write(
129+ ('<launchpad-bugs xmlns="%s">\n' % BUGS_XMLNS).encode('UTF-8'))
130 for count, taskid in enumerate(ids):
131 task = bugtaskset.get(taskid)
132 tree = ET.ElementTree(serialise_bugtask(task))
133- tree.write(output)
134+ tree.write(output, encoding="UTF-8", xml_declaration=False)
135 # Periodically abort the transaction so that we don't lock
136 # everyone else out.
137 if count % 100:
138 ztm.abort()
139- output.write('</launchpad-bugs>\n')
140+ output.write(b'</launchpad-bugs>\n')
141diff --git a/scripts/bug-export.py b/scripts/bug-export.py
142index b06daba..15bf58e 100755
143--- a/scripts/bug-export.py
144+++ b/scripts/bug-export.py
145@@ -33,9 +33,10 @@ class BugExportScript(LaunchpadScript):
146 def main(self):
147 if self.options.product is None:
148 self.parser.error('No product specified')
149- output = sys.stdout
150 if self.options.output is not None:
151 output = open(self.options.output, 'wb')
152+ else:
153+ output = getattr(sys.stdout, 'buffer', sys.stdout)
154
155 product = getUtility(IProductSet).getByName(self.options.product)
156 if product is None:

Subscribers

People subscribed via source and target branches

to status/vote changes: