Merge lp:~mbp/bzr/499637-default-uifactory into lp:bzr

Proposed by Martin Pool on 2010-01-14
Status: Merged
Approved by: John A Meinel on 2010-01-14
Approved revision: 4961
Merged at revision: not available
Proposed branch: lp:~mbp/bzr/499637-default-uifactory
Merge into: lp:bzr
Diff against target: 81 lines (+29/-8)
3 files modified
NEWS (+5/-0)
bzrlib/tests/per_uifactory/__init__.py (+4/-7)
bzrlib/ui/__init__.py (+20/-1)
To merge this branch: bzr merge lp:~mbp/bzr/499637-default-uifactory
Reviewer Review Type Date Requested Status
John A Meinel 2010-01-14 Approve on 2010-01-14
Review via email: mp+17358@code.launchpad.net
To post a comment you must log in.
Martin Pool (mbp) wrote :

This fixes https://bugs.edge.launchpad.net/bzr/+bug/499757 by making SilentUIFactory accept make_output_stream

Martin Pool (mbp) wrote :

Despite the name I haven't fixed bug 449637 here yet, because it causes a somewhat annoying circular import situation to try to set bzrlib.ui.ui_factory to an instance of bzrlib.ui.text.TextUIFactory...

John A Meinel (jameinel) wrote :

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Martin Pool wrote:
> Despite the name I haven't fixed bug 449637 here yet, because it causes a somewhat annoying circular import situation to try to set bzrlib.ui.ui_factory to an instance of bzrlib.ui.text.TextUIFactory...
>

The bug states that the problem is that SilentUIFactory gives a
make_output_stream error. Is there something else going on that I don't
understand?

main() is the helper that sets the ui factory and trace settings. I
think it is reasonable that if someone wants to call 'run_bzr' directly,
they can set things up for themselves. (Otherwise they would call
main(), right?)

Anyway, your change is ok. I think it *does* break people who would be
using run_bzr() directly (without setting a ui_factory). Think of stuff
like run_bzr('diff'). It used to output content to sys.stdout even
without the ui_factory set. However, I can understand that Silent seems
to indicate that there wouldn't be any output.

Though if they are already running things directly, they also have to do
stuff like "install_bzr_command_hooks()". I did test that in bzr/2.0
doing this works and produces output:

from bzrlib import commands
commands.install_bzr_command_hooks()
commands.run_bzr(['diff', '-c', '-1'])

However on bzr.dev it produces a "make_output_stream not supported"
error. With your patch it succeeds, but produces no output.

Not failing is better than failing on every command (even ones that
don't produce output, or don't produce it through make_output_stream()).
I'd be slightly happier if we continued to produce output, but only a bit.

John
=:->
  review: approve
  merge: approve
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAktPL/MACgkQJdeBCYSNAAPqagCeMAgFgmgHks7GacaYIYpdUqdH
tC0AoJZNkA1X6LkcQYVEKQQRB0IUEF7e
=qGMk
-----END PGP SIGNATURE-----

review: Approve
Martin Pool (mbp) wrote :

2010/1/15 John Arbash Meinel <email address hidden>:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Martin Pool wrote:
>> Despite the name I haven't fixed bug 449637 here yet, because it causes a somewhat annoying circular import situation to try to set bzrlib.ui.ui_factory to an instance of bzrlib.ui.text.TextUIFactory...
>>
>
> The bug states that the problem is that SilentUIFactory gives a
> make_output_stream error. Is there something else going on that I don't
> understand?

There are two bugs here:

1- silentuifactory.make_output_stream errors - it would be more
reasonable for it to discard the output
2- the default for bzrlib should probably be text output to
stdout/stderr, as it once was, not silence

#2 was once mostly working because bulk output didn't go through the
uifactory. However, other things that did go through the uifactory
didn't work by default in the way you would have expected. So what's
changed there is just that the scope of the uifactory has grown so the
consequences of not setting one are larger.

This fixes #1; I'd like to fix the second too but it's a bit annoying
to get something from a submodule to initialize a variable in a
supermodule at load time because of circular import restrictions.

> main() is the helper that sets the ui factory and trace settings. I
> think it is reasonable that if someone wants to call 'run_bzr' directly,
> they can set things up for themselves. (Otherwise they would call
> main(), right?)

I think calling main() directly has always worked. The other case is
people just using arbitrary internal bzrlib functions.

> Anyway, your change is ok. I think it *does* break people who would be
> using run_bzr() directly (without setting a ui_factory). Think of stuff
> like run_bzr('diff'). It used to output content to sys.stdout even
> without the ui_factory set. However, I can understand that Silent seems
> to indicate that there wouldn't be any output.
>
> Though if they are already running things directly, they also have to do
> stuff like "install_bzr_command_hooks()". I did test that in bzr/2.0
> doing this works and produces output:
>
> from bzrlib import commands
> commands.install_bzr_command_hooks()
> commands.run_bzr(['diff', '-c', '-1'])
>
> However on bzr.dev it produces a "make_output_stream not supported"
> error. With your patch it succeeds, but produces no output.

So if I don't fix #2 above, they will need to call

make_ui_factory_for_terminal(sys.stdin, ...)

which is reasonable but I think not ideal.

> Not failing is better than failing on every command (even ones that
> don't produce output, or don't produce it through make_output_stream()).
> I'd be slightly happier if we continued to produce output, but only a bit.

--
Martin <http://launchpad.net/~mbp/>

Martin Pool (mbp) wrote :

https://bugs.edge.launchpad.net/bzr/+bug/507710 suggests just giving plugins a bzrlib.initialize() function.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'NEWS'
2--- NEWS 2010-01-14 00:33:43 +0000
3+++ NEWS 2010-01-14 08:45:22 +0000
4@@ -90,6 +90,11 @@
5 * Listen to the SIGWINCH signal to update the terminal width.
6 (Vincent Ladeuil, #316357)
7
8+* ``SilentUIFactory`` now supports ``make_output_stream`` and discards
9+ whatever is written to it. This un-breaks some plugin tests that
10+ depended on this behaviour.
11+ (Martin Pool, #499757)
12+
13 * The 2a format wasn't properly restarting autopacks when something
14 changed underneath it (like another autopack). Now concurrent
15 autopackers will properly succeed. (John Arbash Meinel, #495000)
16
17=== modified file 'bzrlib/tests/per_uifactory/__init__.py'
18--- bzrlib/tests/per_uifactory/__init__.py 2010-01-05 15:52:28 +0000
19+++ bzrlib/tests/per_uifactory/__init__.py 2010-01-14 08:45:22 +0000
20@@ -1,4 +1,4 @@
21-# Copyright (C) 2009 Canonical Ltd
22+# Copyright (C) 2009-2010 Canonical Ltd
23 #
24 # This program is free software; you can redistribute it and/or modify
25 # it under the terms of the GNU General Public License as published by
26@@ -76,12 +76,9 @@
27 self._check_show_warning(msg)
28
29 def test_make_output_stream(self):
30- # at the moment this is only implemented on text uis; i'm not sure
31- # what it should do elsewhere
32- try:
33- output_stream = self.factory.make_output_stream()
34- except NotImplementedError, e:
35- raise tests.TestSkipped(str(e))
36+ # All UIs must now be able to at least accept output, even if they
37+ # just discard it.
38+ output_stream = self.factory.make_output_stream()
39 output_stream.write('hello!')
40
41 def test_transport_activity(self):
42
43=== modified file 'bzrlib/ui/__init__.py'
44--- bzrlib/ui/__init__.py 2009-12-18 16:39:21 +0000
45+++ bzrlib/ui/__init__.py 2010-01-14 08:45:22 +0000
46@@ -1,4 +1,4 @@
47-# Copyright (C) 2005, 2006, 2007, 2008, 2009 Canonical Ltd
48+# Copyright (C) 2005-2010 Canonical Ltd
49 #
50 # This program is free software; you can redistribute it and/or modify
51 # it under the terms of the GNU General Public License as published by
52@@ -296,6 +296,9 @@
53 def get_username(self, prompt, **kwargs):
54 return None
55
56+ def _make_output_stream_explicit(self, encoding, encoding_type):
57+ return NullOutputStream(encoding)
58+
59 def show_error(self, msg):
60 pass
61
62@@ -361,3 +364,19 @@
63
64 def log_transport_activity(self, display=False):
65 pass
66+
67+
68+class NullOutputStream(object):
69+ """Acts like a file, but discard all output."""
70+
71+ def __init__(self, encoding):
72+ self.encoding = encoding
73+
74+ def write(self, data):
75+ pass
76+
77+ def writelines(self, data):
78+ pass
79+
80+ def close(self):
81+ pass