1 # Copyright (C) 2007, Thomas Leonard
2 # See http://0install.net/0compile.html
9 def report_bug(policy
, iface
):
12 # TODO: Check the interface to decide where to send bug reports
14 issue_file
= '/etc/issue'
15 if os
.path
.exists(issue_file
):
16 issue
= file(issue_file
).read().strip()
18 issue
= "(file '%s' not found)" % issue
20 text
= 'Problem with %s\n' % iface
.uri
21 if iface
.uri
!= policy
.root
:
22 text
= ' (while attempting to run %s)\n' % policy
.root
25 text
+= 'Zero Install: Version %s, with Python %s\n' % (zeroinstall
.version
, sys
.version
)
27 text
+= '\nChosen implementations:\n'
30 text
+= ' Failed to select all required implementations\n'
32 for chosen_iface
in policy
.implementation
:
33 text
+= '\n Interface: %s\n' % chosen_iface
.uri
34 impl
= policy
.implementation
[chosen_iface
]
36 text
+= ' Version: %s\n' % impl
.get_version()
37 if impl
.interface
!= chosen_iface
:
38 text
+= ' From feed: %s\n' % impl
.interface
.uri
39 text
+= ' ID: %s\n' % impl
.id
41 text
+= ' No implementation selected\n'
43 text
+= '\nSystem:\n %s\n\nIssue:\n %s\n' % ('\n '.join(os
.uname()), issue
)
45 reporter
= BugReporter(policy
, iface
, text
)
48 class BugReporter(dialog
.Dialog
):
49 def __init__(self
, policy
, iface
, env
):
50 dialog
.Dialog
.__init
__(self
)
51 self
.set_title('Report a Bug')
53 self
.set_has_separator(False)
57 vbox
= gtk
.VBox(False, 4)
58 vbox
.set_border_width(10)
59 self
.vbox
.pack_start(vbox
, True, True, 0)
61 self
.set_default_size(gtk
.gdk
.screen_width() / 2, -1)
63 def frame(title
, contents
, buffer):
66 label
.set_markup('<b>%s</b>' % title
)
67 fr
.set_label_widget(label
)
68 fr
.set_shadow_type(gtk
.SHADOW_NONE
)
69 vbox
.pack_start(fr
, True, True, 0)
71 align
= gtk
.Alignment(0, 0, 1, 1)
72 align
.set_padding(0, 0, 16, 0)
76 self
.frames
.append((title
, buffer))
78 def text_area(text
= None, mono
= False):
79 swin
= gtk
.ScrolledWindow()
80 swin
.set_policy(gtk
.POLICY_AUTOMATIC
, gtk
.POLICY_ALWAYS
)
81 swin
.set_shadow_type(gtk
.SHADOW_IN
)
84 tv
.set_wrap_mode(gtk
.WRAP_WORD
)
87 tv
.get_buffer().insert_at_cursor(text
)
90 tv
.modify_font(pango
.FontDescription('mono'))
92 tv
.set_accepts_tab(False)
94 return swin
, tv
.get_buffer()
97 frame("What doesn't work?", *actual
)
99 expected
= text_area()
100 frame('What did you expect to happen?', *expected
)
102 errors_box
= gtk
.VBox(False, 0)
103 errors_swin
, errors_buffer
= text_area(mono
= True)
104 errors_box
.pack_start(errors_swin
, True, True, 0)
105 buttons
= gtk
.HButtonBox()
106 buttons
.set_layout(gtk
.BUTTONBOX_START
)
107 errors_box
.pack_start(buttons
, False, True, 4)
108 get_errors
= gtk
.Button('Run it now and record the output')
109 get_errors
.connect('clicked', lambda button
: self
.collect_output(errors_buffer
))
110 buttons
.add(get_errors
)
112 frame('Are any errors or warnings displayed?', errors_box
, errors_buffer
)
114 if dialog
.last_error
:
115 errors_buffer
.insert_at_cursor(str(dialog
.last_error
))
117 environ
= text_area(env
, mono
= True)
118 frame('Information about your setup', *environ
)
120 self
.add_button(gtk
.STOCK_CANCEL
, gtk
.RESPONSE_CANCEL
)
121 self
.add_button(gtk
.STOCK_OK
, gtk
.RESPONSE_OK
)
122 self
.set_default_response(gtk
.RESPONSE_OK
)
125 if r
== gtk
.RESPONSE_OK
:
127 for title
, buffer in self
.frames
:
128 start
= buffer.get_start_iter()
129 end
= buffer.get_end_iter()
130 text
+= '%s\n\n%s\n\n' % (title
, buffer.get_text(start
, end
).strip())
131 title
= 'Bug for %s' % iface
.get_name()
132 self
.report_bug(title
, text
)
134 dialog
.alert(self
, "Your bug report has been sent. Thank you.",
135 type = gtk
.MESSAGE_INFO
)
138 self
.connect('response', resp
)
142 def collect_output(self
, buffer):
144 from zeroinstall
.injector
import run
146 iter = buffer.get_end_iter()
147 buffer.place_cursor(iter)
149 if not self
.policy
.ready
:
150 missing
= [iface
.uri
for iface
in self
.policy
.implementation
if self
.policy
.implementation
[iface
] is None]
151 buffer.insert_at_cursor("Can't run: no version has been selected for:\n- " +
152 "\n- ".join(missing
))
154 uncached
= self
.policy
.get_uncached_implementations()
156 buffer.insert_at_cursor("Can't run: the chosen versions have not been downloaded yet. I need:\n\n- " +
157 "\n\n- " . join(['%s version %s\n (%s)' %(x
[0].uri
, x
[1].get_version(), x
[1].id) for x
in uncached
]))
170 logger
= logging
.getLogger()
171 logger
.setLevel(logging
.DEBUG
)
172 run
.execute(self
.policy
, self
.policy
.prog_args
)
175 traceback
.print_exc()
180 reader
= os
.fdopen(r
, 'r')
185 iter = buffer.get_end_iter()
186 buffer.place_cursor(iter)
188 # Cope with invalid UTF-8
190 decoder
= codecs
.getdecoder('utf-8')
191 data
= decoder(reader
.read(), 'replace')[0]
193 buffer.insert_at_cursor(data
)
196 pid
, status
= os
.waitpid(child
, 0)
201 def report_bug(self
, title
, text
):
204 from urllib2
import urlopen
206 stream
= urlopen('http://sourceforge.net/tracker/index.php',
217 # Write to stderr in the hope that it doesn't get lost
218 print >>sys
.stderr
, "Error sending bug report: %s\n\n%s" % (title
, text
)