[MERGE] Support for Putty SSH implementation

John Arbash Meinel john at arbash-meinel.com
Mon Jan 8 17:03:23 GMT 2007


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

Andrew Bennetts wrote:
> Dmitry Vasiliev wrote:
>> The attached patch adds support for Putty's plink SSH implementation. 
>> Also slightly refactored SSH negotiation code and added some tests.
> 
> I like the look of this.  Some comments, mostly about making the intent of some
> code clearer:
> 
> bzrlib/tests/test_ssh_transport.py
> ----------------------------------
> 
> [...]
>> +
>> +    def test_default_vendor(self):
>> +        manager = TestSSHVendorManager()
>> +        self.assertRaises(SSHVendorNotFound, manager.get_vendor, {})
>> +        manager.register_vendor("default", "VENDOR")
>> +        self.assertEqual(manager.get_vendor({}), "VENDOR")
> 
> An explicit comment or docstring in the test stating that "default" as a vendor
> name is treated specially would be good.  It's not hard to guess, but making the
> intent explicit is good, in case someone guesses incorrectly :)
> 
>> +    def test_cached_vendor(self):
>> +        manager = TestSSHVendorManager()
>> +        self.assertRaises(SSHVendorNotFound, manager.get_vendor, {})
>> +        manager.register_vendor("vendor", "VENDOR")
>> +        self.assertRaises(SSHVendorNotFound, manager.get_vendor, {})
>> +        self.assertEqual(manager.get_vendor({"BZR_SSH": "vendor"}), "VENDOR")
>> +        self.assertEqual(manager.get_vendor({}), "VENDOR")
> 
> The intented behaviour here isn't immediately obvious to me.  Why should
> manager.get_vendor({"BZR_SSH": "vendor"}) change the result of a later
> manager.get_vendor({}) call?
> 
> Basically, I'd like to see a comment (or docstring) in this test explain the
> intent.  Something like "Once SSHVendorManager.get_vendor successfully returns
> a vendor, later invocations will return the same vendor, regardless of changes
> to the environment.", but that doesn't sound quite right to me.  How you would
> explain this behaviour, and the reason for it?
> 
> I'd also be tempted to use something other than "VENDOR" here, e.g. "vendor =
> object()", so that you can add "self.assertIdentical(vendor,
> manager.get_vendor(...))", i.e. demonstrate that it's the exact same object.
> (You could technically do it with the string object, but string identity is
> mildly confusing due to interning, so using an object would be better.)
> 
>> +    def test_vendor_getting_methods_precedence(self):
>> +        manager = TestSSHVendorManager()
>> +        self.assertRaises(SSHVendorNotFound, manager.get_vendor, {})
>> +
>> +        manager.register_vendor("default", "DEFAULT")
>> +        self.assertEqual(manager.get_vendor({}), "DEFAULT")
>> +
>> +        manager.ssh_vendor = None
>> +        manager.set_ssh_version_string("OpenSSH")
>> +        self.assertIsInstance(manager.get_vendor({}), OpenSSHSubprocessVendor)
>> +
>> +        manager.ssh_vendor = None
>> +        manager.register_vendor("vendor", "VENDOR")
>> +        self.assertEqual(manager.get_vendor({"BZR_SSH": "vendor"}), "VENDOR")
>> +
>> +        self.assertEqual(manager.get_vendor({}), "VENDOR")
> 
> This test could use some comments as well.  What's the "precendence" you're
> testing?  Peeking at the implementation, I guess this is testing the order that
> get_vendor attempts to choose a vendor, i.e. by environment variable, by
> inspection, by default, and finally by giving up.  Say so explicitly in the test
> (including naming the stages in the test)!
> 
> Also, the purpose of the "manager.ssh_vendor = None" lines probably deserves a
> comment explaining that this is clearing the cache.  Perhaps it would be clearer
> to create a fresh TestSSHVendorManager each time, although you'd have to repeat
> some registrations, so perhaps not.
> 
> I'm mildly surprised that "ssh_vendor" isn't "_ssh_vendor", it doesn't look like
> something that most code ought to be mucking with.
> 
> NEWS
> ----
> 
>>    IMPROVEMENTS:
>>  
>> +    * Added support for Putty's SSH implementation. (Dmitry Vasiliev)
>> +
> 
> You're being overly modest.  You've done a nice cleanup of SSH vendor
> registration too! :)   (although mentioning that probably belongs under the
> INTERNALS heading).
> 
> 
> bzrlib/errors.py
> ----------------
> 
> [...]
>> +class SSHVendorNotFound(BzrError):
>> +
>> +    _fmt = "Don't know how to handle SSH connections. Please set BZR_SSH environment variable."
> 
> Lines should have no more than 79 characters (PEP 8).
> 
> 
> bzrlib/transport/ssh.py
> ------------------------
> 
> [...]
>>                             SocketConnectionError,
>>                             TransportError,
>>                             UnknownSSH,
>> +                           SSHVendorNotFound,
>>                             )
> 
> I don't think this convention is documented anywhere (I don't see it in HACKING
> or PEP 8), but the other names being imported from bzrlib.errors there are in
> alphabetical order; I think it would be good to keep that ordering.
> 

IIRC, PEP8 says that imports should be in sorted order. I think we just
took it such that if

import bar
import foo

is in sorted order, then

from x import (
  bar,
  foo,
  )

should also be in sorted order.

John
=:->



-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.3 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFFonlbJdeBCYSNAAMRAkJsAKCimE5p+pzYvxAbQ9EDnNxDqJ/7IACfZT1C
NoGXd15eYYWKtAgsf6ufmT8=
=JYI7
-----END PGP SIGNATURE-----



More information about the bazaar mailing list