Select Page

Moving from low class to high class – about 15 minutes

Our class has done a reasonable job of wrapping up our concept of a host. We can make some improvements to the class that make it a little easier and safer to use from the outside. The class has some parameters that are required, such as device_name, and some parameters that are optional, like the idea of a key file name for asymmetric key authentication. So let’s take a swing at making three improvements:

  1. Accept a dictionary of parameters to SSHHost constructor plus verify them.
  2. Make clearer the call to create the SSHHost.
  3. Prompt for a password if it’s missing.

Mostly we just need to change our constructor and how we create an instance of the SSHHost class. Let’s tackle the calling site first and see how we’ll clarify the instance creation. Initially we had:

At first glance that doesn’t too bad. It’s helpful that we’ve named our variables nicely. But what if we made, gasp, a mistake and switched the order of our parameters?

It’s hard to say whether that’s correct, isn’t it? We can improve the program by making it clear what parameters are being passed to the class.

Now we’re creating a dictionary with three named elements. The dictionary itself is just

Now we can see that the program is mapping data from the row array to the named keys in the dictionary. Let’s take a look at how we can make use of the data we’ve put into our little dictionary. The dictionary is still a parameter to our SSHHost constructor, but we can update that constructor to be:

We’re simply saving our incoming parameters dictionary to an instance variables also named parameters. Then we’re setting the same old instance variables by reading data from our parametersinstance variable. That works and you would be pleasantly successful with that code. However, we have introduced the possibility of a programmer misspelling a parameter and breaking things.

The proudent thing, dude, is to make sure that the parameters dictionary contains at least the values we need and doesn’t contain anything we don’t know how to handle. In the iteration below we add a little error checking to make sure that all of the required_parameters are present and that we don’t get anything we don’t recognize (represented in all_parameters).

We have added a first loop to verify that we get every parameter we need in our constructor. Since required_parameters is a list containing all of the, well, required parameters then we can go through the list and make sure that we’ve got them all. To do this we:

The for statement goes through the list required_parameters and, one by one, loads the values into param and executes code inside the for loop. Inside the loop the if statement checks to see whether param‘s value, for example device_name, is actually inside our self.parameters dictionary. If we can’t find the param value then we raise an exception. Otherwise we keep going through the dictionary through to the end.

Now that we’ve verified that we have everything we require we need to do kind of the opposite. We’re going to check to make sure that there isn’t anything in self.parameters that is unfamiliar to us. The reason for this is to make sure that no one has attempted to pass us a parameter for which we are unprepared. That could cause a bit of confusion. For example someone could add a new parameter and assume that our constructor will handle that parameter. In there interest of clarity we are going to reject any parameters that don’t make sense to us. Here’s our checking code:

 

First we need to add together all of the acceptable parameters, which is the combination of required_parameters and optional_parameters. Python makes it much easier than a lot of other languages to add the two lists together. The syntax is pretty simple addition-style syntax.

Next we have a for loop that goes through all of the incoming self.parameters, checking the values one by one. If we find a case where key not in all_parameters then we whine and complain by raising an exception.

Next we can add the password checking. We’ll update the constructor to be clear about whether we have a password (or set our password variable to None.

We do set it to None to make sure that we really know we don’t have a password. We’re also doing a minimal check to make sure the len() of the password is more than 0 characters long.

Later, in our connect() method we can add a little bit of code to ask the user to provide a password if ours is None. Here’s what that looks like:

We import the Python getpass module so that we can prompt the user for a password without echoing the password to the screen.

That should be pretty straightforward.

Share This