Keith Mitchell wrote:
> Hi Joe,
> 
> Thank you for taking the time to review. My comments are below. 
> Incidentally, you've brought up some very good points that have made me 
> go "hrmmmm," so I'd say it's a worthwhile review!

Thanks Keith. I'm glad my input was valuable.

Thank you for your reply. I think all of your feedback to me is great. I 
have made some comments below.

Joe

> 
> - Keith
> 
> Joseph J VLcek wrote:
>>
>> Hey Keith,
>>
>> Here is my feedback. Many of my comments are nit/questions. My Python 
>> experience is limited still. So many of my comments my be due to naivety.
>>
>> I may have learned more from doing this review than I provide.
>>
>> Hope this help.
>> Joe
>>
>> ---
>>
>> +-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=
>>  
>>
>> From code walkthrough:
>> +-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=
>>  
>>
>>
>> Comment:
>> --------
>>
>> scroll_window.py
>>
>>     I have a comment about init_scroll_bar.
>>
>> disk_window.py has:
>>                 self.right_win.init_scroll_bar()
>>
>>     Why init_scroll_bar is sometimes passed, FALSE, TRUE and
>> nothing indicates to me this is not a BOOLIAN. It actually has
>> 3 values. I think the argument should accept something like:
>>
>> DRAW_SCROLL_BAR, REMOVE_SCROLL_BAR, UNALTER_SCROLL_BAR
> 
> While I see your point, I'm not sure I agree with the need to create a 
> separate enum-type setup to cover this scenario. Essentially, I've 
> combined functionality that could be separated into a single function 
> (i.e., "set/get_use_scroll_bar" and "repaint_scroll_bar"). If the 
> current setup makes usage non-obvious, I think splitting the 
> functionality would be simpler, and more readable. That is, have 
> "init_scroll_bar" always just read _use_scroll_bar, and then provide a 
> setter function for _use_scroll_bar that calls init_scroll_bar if 
> needed. Then, init_scroll_bar doesn't need the "3-way boolean," and the 
> setter would only take a "True" or "False" as an argument.

Great! I like your solution.

> 
>>
>> Comment:
>> --------
>>
>> Why the x_loc/y_loc level window management? Isn't there already
>> something which exists that can be used by Python to do this on
>> a char. based screen?
> 
> Interesting. Perhaps our initial research wasn't quite deep enough. I'll 
> look into it some, but I don't think rewriting at this stage will be 
> useful.
> 
>>
>> e.g.: http://excess.org/urwid/
> 
> Several of the more complex examples in their tutorial seem make use of 
> either relative or absolute x/y coordinates. Certainly, they do a better 
> job of abstracting some of it away then what was done here, but I can't 
> envision any UI framework that doesn't provide the option of explicitly 
> setting coordinates in some fashion.

Thanks for considering this. I agreed that a UI framework likely needs 
this functionality but abstracting it as much as feasible seems valuable 
to me. That's the point I was trying to make.


> 
>>
>> +-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=
>>  
>>
>> Comment from code I deskcheck reviewed:
>> +-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=+-=
>>  
>>
>>
>> I reviewed:
>>
>>     cmd/text-install/osol_install/text_install/date_time.py
>>     cmd/text-install/osol_install/text_install/help_screen.py
>>     cmd/text-install/osol_install/text_install/network_nic_configure.py
>>     cmd/text-install/osol_install/text_install/network_nic_select.py
>>     cmd/text-install/osol_install/text_install/network_type.py
>>     cmd/text-install/osol_install/text_install/partition_edit_screen.py
>>     cmd/text-install/osol_install/text_install/timezone.py
>>     cmd/text-install/osol_install/text_install/timezone_locations.py
>>     cmd/text-install/osol_install/text_install/timezone_regions.py
>>
>> General comments
>> -------------------------------------------------------------------------------
>>  
>>
>>
>> Comment:
>> --------
>> Is this code supposted to be PEP8 ?
> 
> Yes (see below). This code should be PEP8 and pylint clean, or nearly 
> so. I see scores mostly in the 9-10 range.
> 
>>
>> e.g.:
>> pylint --include-ids=y --rcfile=../../tools/env/install.pylintrc 
>> help_screen.py
>>     ...
>>     Your code has been rated at 3.65/10
>>
>> pylint --include-ids=y --rcfile=../../tools/env/install.pylintrc 
>> partition_edit_screen.py
>>     ...
>>     Your code has been rated at 0.75/10
>>
>> pylint --include-ids=y --rcfile=../../tools/env/install.pylintrc 
>> network_nic_select.py
>>     ...
>>     Your code has been rated at -0.53/10
>>
>>
>>
>> Comment:
>> --------
>> Please add pydoc usable comments for each file.
>>
>> e.g.:
>> % pydoc network_nic_configure.py
>> no Python documentation found for 'network_nic_configure.py'
> 
> For this, and pylint, you'll need to run from the 
> usr/src/cmd/text-install directory. Otherwise, both pydoc and pylint 
> can't resolve the imports properly. Pylint will work properly if you add 
> that directory to your PYTHONPATH, but pydoc will still get confused if 
> you reference the file directly. However, you can set the PYTHONPATH, 
> and then run "pydoc osol_install.text_install.network_nic_configure". I 
> imagine that other caiman code that imports osol_install.<something> 
> suffers similarly in a "clean" environment, but since I most of the code 
> is installed on the system already, it can at least reference the latest 
> release version. That brings up a good point, actually - one must be 
> sure to set the PYTHONPATH appropriately so that when we run pylint 
> before checkin, pylint is checking the updated versions of imported 
> modules, not the installed versions.

Ah yes. Thanks!

> 
>>
>>
>> Comment:
>> --------
>>
>> This is a comment I made during the code walkthrough sessions. I think
>> the manipulation of the x & y coordinates should be done at a lower
>> level. Pehaps a text_install/CoursePosition class could be defined.
>> Maybe not worth it. But since it came up in the walkthrough sessions
>> I thought I would note it.
> 
> Do you see "CoursePosition" as a simple (x, y) "Point" type class, or 
> something more complex? Are you referring to the manipulation in the 
> screen code of, for example "y_loc += <something>"? I sort of see the 
> problem you're poking at, but I'm not sure what the solution might look 
> like yet.

At least abstracting the x,y code... If evaluation results in more 
complete solution that might be valuable...



> 
>>
>>
>>
>> cmd/text-install/osol_install/text_install/date_time.py
>> -------------------------------------------------------------------------------
>>  
>>
>>
>> Comment:
>> --------
>> It seems you may be reinventing the wheel here. his seems like basic 
>> functionality
>> to me.
>>
>> Perhaps exploring what Python base classes already exhist that could 
>> handle
>> more of the functionality defined in date_time.
> 
> The 'datetime' module is used in this file. Are there particular 
> instances in this file that you think deserve extra attention?

I see where you use datetime and I took at look at what datetime 
provides and maybe I'm wrong but it seemed to me that you may be 
duplicating what datetime is doing/providing.

> 
>>
>> Comment:
>> --------
>> It also seems to me that the x & y courser manipulation seels like basic
>> functionality that might be already available somewhere. It's low level
>> functionality that seems to me should belong at a lower level.
>>
>> Comment:
>> --------
>>   I found these varible names not very indicative:
>>   55     YYYY = _("(YYYY)")
>>   YEAR maybe better
> 
> How about YEAR_FORMAT? Given the number of other variables in this file 
> with "year" or "YEAR" in them, calling it just plain "YEAR" would be 
> more ambiguous.


Sound good to me.



> 
>>
>>   60     OFFSET = 3
>>   OFFSET to what?
> 
> Answering the explicit question: Offset from the left side of the 
> window. Most/all screens have an OFFSET variable, and the UI elements 
> within the screens tend to be given OFFSET blank columns to their left.
> 
> To answer the implied question: Removing the usage of OFFSET, and 
> instead doing something along the lines of adding a "border" (or 
> "left/right/top/bottom_border") property to InnerWindow, would condense 
> this and make it  more intelligent. (border/offset/padding, something 
> along those lines).
> 
>>
>> Comment:
>> --------
>>   61     YEAR_DIGITS = 4
>>
>> Comment:
>> --------
>>
>>   84         self.year_edit = None
>>   85         self.year_err = None
>>   86         self.year_list = None
>>
>> _edit, _err, _list are repeated. Do you think it might be better to 
>> put these in a
>> dictionary with keys: edit, err and list?
> 
> There's a common paradigm in this and other code of "EditField inside of 
> a ListItem, with an associated ErrorWindow". I think we can take your 
> suggestion a step further and:
> * Provide a common, easier way to construct an "EditField inside of a 
> ListItem with an ErrorWindow" globject.
> * Strip these down to just "self.year_field" or something similar. The 
> year_list and year_err fields are rarely directly used, and if they're 
> needed, they could be referenced by, for example, 
> self.year_field.list_item and self.year_field.error_win, respectively.
> 
>>
>> Comment:
>> --------
>>  178         self.edit_area.columns = 3
>>
>> Hardcoding things like this raises a flag for maintenance issues.
>> Would   60     OFFSET = 3 work here?
> 
> OFFSET wouldn't be the right variable, but moving the hardcoded value to 
> a class property would definitely be preferred.
> 
>>
>> Comment:
>> --------
>>  151         y_loc += 1
>> ....
>>  260         self.center_win.add_text("(0-59)", y_loc, x_loc, 
>> self.win_size_x - 3)
>>
>> The code between lines 151 and 260 looks repetitious. Would it make sense
>> to create parameterized supporting code which could be invoked 
>> multiple times
>>
>> to:
>>
>> As needed set things like:
>>  self.error_area.y_loc
>>  self.list_area.y_loc
>>  self.list_area.columns
>>  self.edit_area.columns
>>  self.edit_area.x_loc
>>
>> invoke:
>>     ErrorWindow()
>>     ListItem()
>>     EditField()
> 
> Agreed. Part of this could be stripped down when the unified 
> "EditField/ListItem/ErrorWindow" concept from above is in place.
> 
>>
>> comment:
>> --------
>>
>>  326 def get_days_in_month(month_edit, year_edit, date_time):
>>
>> Could calendar.py  monthrange be leveraged here?
> 
> It is - see lines 347 and 350. The extra logic handles cases not covered 
> (for example, the user hasn't finished inputting the month or year yet, 
> so we need to have intelligent defaults given the remaining known data).
> 
>>
>> comment:
>> --------
>>  345             if (len(cur_year) == 4 and year_valid(year_edit)):
>>
>> Could calendar.py  isleap be leveraged here?
> 
> This is checking to see if the user has input a valid year yet, e.g., 
> they could be halfway through typing "2010" and so there would only be a 
> "20" in the field. We don't actually want to look up the monthrange for 
> the year "20" in this case. However, it looks like the call to 
> year_valid is unnecessary and potentially toxic.


Well at least my erroneous comment lead you to detect the potentially 
toxic part. ;)



> 
>>
>> cmd/text-install/osol_install/text_install/help_screen.py
>> -------------------------------------------------------------------------------
>>  
>>
>>
>> Comment:
>> --------
>>
>> 67         self.help_info = []
>> 68         self.help_dict = None
>>
>> Does it makes sense to set these empty and to None when:
>>     73         self.setup_help_data()
>>     will fill them in?
> 
> Yes. Pylint and pydoc prefer variables to be 'announced' in the __init__ 
> function.
> 
>>
>> Comment:
>> --------
>>
>>   92             "NICSelect": ("network_manual.txt",
>>   ...
>>   94             "NICConfigure": ("network_manual.txt",
>>
>> Are both of these supposed to have the same helpfile: 
>> "network_manual.txt"?
>>
>> Maybe yes eh?
> 
> Yes. The one file contains the help text for both screens (the first 
> screen is not terribly complicated).
> 
>>
>>
>> Comment:
>> --------
>>
>>   96             "TimeZoneRegions":  ("timezone.txt", _("Time Zone")),
>>   97             "TimeZoneLocations": ("timezone.txt", _("Time Zone")),
>>   98             "TimeZone": ("timezone.txt", _("Time Zone")),
>>
>> Are all of these supposed to have the same header? I could see maybe the
>> same help file but should the headers be different?
>>
>> Maybe no eh?
> 
> Given that the text is the same, I think the headers should remain the 
> same.
> 
>>
>> Comment:
>> --------
>>  105         if self.is_x86:
>>  130         if self.is_x86:
>>
>> Could/Should these two conditionals be combined?
> 
> Yeah they can. Should they? It's a readability issue, and the 
> performance difference would be unnoticeable if combined. Keeping the 
> help_info appends grouped and the help_dict entries grouped seems 
> preferable.

OK. Thanks for considering it.


> 
>>
>> Comment:
>> --------
>>  202             help_text = self.get_help_topic(info[0])
>> ...
>>  207             help_topic = info[0]
>>
>> I see an inconsistency:
>>
>> help_text is set using get_help_topic yet help_topic is not. Is this 
>> wrong
>> or is the named backwards?
> 
> I'll have to defer to Sue on this one.
> 
>>
>> cmd/text-install/osol_install/text_install/network_nic_configure.py
>> -------------------------------------------------------------------------------
>>  
>>
>>
>> Comment:
>> --------
>>
>>  101             find_defaults = self.nic.find_defaults
>>
>> Why is it necessarey to have this in a try/except block? You control
>> self.nic.find_defaults.
>>
>> This may be a Python thing I just don't understand yet.
> 
> No, it's wrong. It's a remnant of the original version of NetworkInfo, 
> for which this was the easier way to write things. The more appropriate 
> route would be to either add find_defaults to NetworkInfo.__init__ 
> (defaulting to True), or to change 100-103 to:
> 
> find_defaults = getattr(self.nic, "find_defaults", True)


Cool! I found one! ;)



> 
>>
>> Comment:
>> --------
>>
>>  157         self.center_win.activate_object(0)
>>
>> What does the "0" represent? Could a defintion be created for index 0 so
>> an indicative name could be seen here?
> 
> The 0 represents the first item in the list. We could do 
> "self.center_win.activate_object(self.ip_field)", which is *currently* 
> the first item in the list, but setting it to 0 here (and on other 
> screens) simply means "default to 0". Perhaps, though, 
> activate_object()'s first parameter should be optional, and default to 
> the "first item," instead.

I like that approach.


> 
>>
>> Comment:
>> --------
>>
>>  168         list_item.data_obj = label
>>
>> Could the ListItem constructor set this even though it is in 
>> inner_window?
> 
> InnerWindow.__init__ doesn't do anything with "data_obj" either, though 
> perhaps it should. Although in a more general sense, the data_obj field 
> is rather odd when I look at it again - it's used to generically link 
> some "data object" to the field for later manipulation. It's used mostly 
> for ListItems, to return the actual Python object associated with the 
> selected list item. It's also used in DiskWindow as a way to associate a 
> specific field with a specific partition (or slice) during editing.
> 
> I'm open to suggestions on making this concept/need simpler, more 
> intuitive, and less "hacky."


Maybe we could talk this through. I don't have the solution but if you 
think bouncing ideas off me could be helpful let me know.


> 
>>
>> Comment:
>> --------
>>
>>  170             validate = incremental_validate
>> Is an arguement needed to incremental_validate?
> 
> No. I want to pass in the function itself, not the result of the 
> function. EditField will call the function after each keystroke.
> 
> 
>>
>> Comment:
>> --------
>>
>> 238 def incremental_validate(edit_field):
>>
>> I find this name misleading. incremental_validate what?
> 
> An IP address. So I suppose "incremental_validate_IP" would be better, yes?

Yes, I think so.


> 
>>
>> Comment:
>> --------
>>
>> 222 def validate_ip(edit_field):
>> 238 def incremental_validate(edit_field):
>>
>> Wouldn't these be better defined in ../profile/ip_address.py ?
> 
> The "grunt work" is done in ip_address.py (IPAddress.convert_address and 
> IPAddress.incremental_check are called by these functions). The 
> functions here catch errors, and raise an error with a (potentially 
> translated) error message pertinent to the UI context in which the error 
> occurred.
> 
>>
>> Comment:
>> --------
>>
>> Support for IPv6?
> 
> Not at this time.
> 
>>
>> cmd/text-install/osol_install/text_install/network_nic_select.py
>> -------------------------------------------------------------------------------
>>  
>>
>>
>> Looks good.  No new comments.
>>
>> cmd/text-install/osol_install/text_install/network_type.py
>> -------------------------------------------------------------------------------
>>  
>>
>>
>> Comment:
>> --------
>>
>> 149         if self.install_profile.no_install_mode:
>>
>>
>> I think it would be valuabel to add a comment describing what
>> no_install_mode is -  manual vs no_instal
> 
> This check won't be in the final version, once the manual networking 
> pieces are available in the backend (it's in here in the meantime so 
> that QE can continue writing tests against the manual network config 
> screens).
> 
> "no_install_mode" itself is explained in text-install.py and referenced 
> in install_progress.py.
> 
>>
>> Comment:
>> --------
>>
>> 184     def validate(self):
>>
>> Can you add a comment that this function overrides BaseScreen.validate?
>> This applies to all functions which override base class functions.
> 
> I'm not convinced that this is the best way to document such a thing. 
>  From my perspective, I think methods from subclasses are generally 
> assumed to either override base class functions or provide extended 
> functionality beyond the base class. On the other hand, assumptions tend 
> to cause confusion.
> 
> The pydoc for NICConfigure does a decent job of conglomerating the 
> necessary information - it shows the docstring for validate_loop() 
> (coming from BaseScreen), which calls itself out as the caller of 
> validate, and validate as coming from NICConfigure.
> 
> I guess my main concern is that adding it to the comment of each 
> function that overrides another function seems like overkill, and seems 
> like there should be a more automated way to make those connections 
> obvious.


Agreed. Now that I know how to run the pydoc.

> 
>>
>> cmd/text-install/osol_install/text_install/partition_edit_screen.py
>> -------------------------------------------------------------------------------
>>  
>>
>>
>> Comment:
>> --------
>>
>>   81         self.slice_mode = slice_mode
>>
>> If this is this x86 specific would the name self.slice_mode_x86 be 
>> helpul?
> 
> "self.x86_slice_mode", but yes, I agree adding the 'x86' portion makes 
> it more helpful.
> 
>>
>> Comment:
>> --------
>>
>>   85         if self.slice_mode: # x86, Slice within a partition
>> ...
>>   90         elif self.is_x86: # x86, Partition on disk
>> ...
>>   94         else: # SPARC (Slice on disk)
>>
>> Does this logic miss a possible error case where it's not slice_mode or
>> is_x86 or SPARC?
>>
>> Suggestion:
>>
>>     if self.slice_mode: # x86, Slice within a partition
>> ...
>>     elif self.is_x86: # x86, Partition on disk
>> ...
>>     elif self.is_sparc: <- would need to add this
>> ...
>>     else:
>>         handle error/exception
> 
> I don't quite follow. The only potential scenarios are:
> x86 partitions
> x86 slices
> SPARC slices
> 
> What other scenario were you thinking might occur?

Ah OK in looking at this again I see. My mistake.


> 
>>
>>
>> Comment:
>> --------
>>
>>  122     def _show(self):
>> and
>>  214     def validate(self):
>>
>> Can you add a comment that this function overrides BaseScreen's?
>>
>> This applies to all functions which override base class functions.
>>
>> Comment:
>> --------
>>
>>  139             logging.error('not skipping slice')
>>
>> Is this a: "all is well" message? If so it could end up confusing the 
>> user.
> 
> This is an errant debugging message. It'll be removed.
> 
>>
>>
>> Comment:
>> --------
>>
>>  143             except AttributeError:
>>
>> Whey doesn't this raise or report an error? Please add a comment 
>> describing
>> this.
> 
> In looking at this code again, I'm not sure why I don't re-raise and 
> fail here. I'll remove the try/except around this (or possibly re-raise 
> a more informative error message), as if this situation occurs, 
> something is broken.

OK that's even better.


> 
>>
>> Comment:
>> --------
>>
>>  220         if self.is_x86 and not self.slice_mode:
>>
>> Is a condition to handle SPARC needed here?
> 
> The "else" case covers slice editing for both x86 and SPARC in this 
> particular instance.
> 
>>
>> cmd/text-install/osol_install/text_install/timezone.py
>> -------------------------------------------------------------------------------
>>  
>>
>>
>> Comment:
>> --------
>>
>>  132                 if len(item[2]) > 0:
>> ...
>>  135                 elif len(item[1]) > 0:
>>
>> Why not use this?
>>
>>   if item[2]:
>> ...
>>   elif item[1]:
>> ...
>>
>> cmd/text-install/osol_install/text_install/timezone_locations.py
>> -------------------------------------------------------------------------------
>>  
>>
>>
>> Comment:
>> --------
>>
>>  142                 if len(item[2]) > 0:
>> ...
>>  145                 elif len(item[1]) > 0:
>>
>> Why not use this?
>>
>>   if item[2]:
>> ...
>>   elif item[1]:
>> ...
>>
>>
>> cmd/text-install/osol_install/text_install/timezone_regions.py
>> -------------------------------------------------------------------------------
>>  
>>
>>
>>  116                 if len(item[2]) > 0:
>> ...
>>  119                 elif len(item[1]) > 0:
>>
>> Why not use this?
>>
>>   if item[2]:
>> ...
>>   elif item[1]:
>> ...
> 
> Good idea on all 3 counts.
> 
>>
>> Comment:
>> --------
>>
>> No other new comments, except:
>>
>> The code in timezone.py,  timezone_locations.py and timezone_regions.py
>> seem to have a lot in common. Would developing a common base class, for
>> shared code, make sense?
> 
> Indeed it would. We'll get on it!

OK Thanks!

> 
>>
>>
>>
>>
>>


Reply via email to