Hi Ethan,
Thank you for your comments. My responses in-line.
Thank you,
Clay
On Mon, 28 Sep 2009, Ethan Quach wrote:
>>> usr/src/cmd/installadm/installadm_common.py
>>> -------------------------------------------
>>> 36 - What's the significance of using the name "Unix" here?
>>
>> None much. It was suggested in the code walk through by someone. However,
>> it has no meaning and perhaps should just be File_ as it just trivially
>> extends the file class.
>
> Okay, can you please go ahead and make this change then. My
> concern was that if our goal for this code is for it to approach
> something portable, then naming something that wasn't necessarily
> Unix specific with that name could cause confusion down the line.
This has been changed. The class is now known as File_()
>>> 65 - In this method, if newlines = False, and blanklines = True,
>>> what will get returned at 107 when processing a blankline in
>>> from a file? An empty string '' ??
>>
>> An empty string would be returned but from line 104 not 107. Why, are you
>> thinking a particular use should be warned against in the docstring?
>
> Sorry, that's what I meant to ask about, the earlier return at 105ish.
>
> Let me restate the comment then...
>
> At 107, it returns the empty string to denote to the caller that we're
> out of lines, but if we're returning the empty string at 105 for the
> case above, then won't the caller get confused?
Yes, this is a very good realization. Thank you! I've modified readlines
to perform the newline removal for now so that this problem is not hit.
> i.e. if we're processing a file with an empty line in the middle of
> the file somewhere, and its being processed with newlines = False and
> blanklines = True, won't this wad of code (readlines() + readline() )
> stop processing in the middle of the file?
>
>>>
>>> usr/src/cmd/installadm/delete-service.py
>>> ----------------------------------------
>>> 413 - I dislike how you have to visit an additional time just
>>> to check existence. I thought there existed some NO_IDX
>>> exception when searching a list. If so, you can then just
>>> wrap 415 in a try
>>
>> Hi Ethan, there is a ValueError thrown. I think we're getting into pretty
>> micro-style/optimization here. However, I can change the code from:
>>
>> To find out this is a value error, try:
>>>>> a=[1,2]
>>>>> a[3]
>> Traceback (most recent call last):
>> File "<stdin>", line 1, in ?
>> IndexError: list index out of range
>>
>> (This is what vfstabObj.fields.MOUNT_POINT[idx] could in all fairness
>> raise)
>>
>>>>> a.index(3)
>> Traceback (most recent call last):
>> File "<stdin>", line 1, in ?
>> ValueError: list.index(x): x not in list
>>
>> (This is what vfstabObj.fields.MOUNT_POINT.index(boot_archive) would raise)
>>
>> Thus the code now reads:
>>
>> # look for filesystem in /etc/vfstab
>> try:
>> # calculate index for mount point
>> idx = vfstabObj.fields.MOUNT_POINT.index(boot_archive)
>> try:
>> # remove line containing micro root
>> del(vfstabObj.fields.MOUNT_POINT[idx])
>> except IOError, e:
>> sys.stderr.write(str(e) + "\n")
>> # microroot was not found in /etc/vfstab
>> except (ValueError, IndexError):
>> sys.stderr.write (_("Microroot for service %s " +
>> "not in vfstab.\n") % service.serviceName)
>> return
>>
>>> try:
>>> idx = vfstabObj.fields.MOUNT_POINT.index(boot_archive)
>>>
>>> try:
>>> # remove line containing micro root
>>> del(vfstabObj.fields.MOUNT_POINT[idx])
>>> except IOError, e:
>>> sys.stderr.write(str(e) + "\n")
>>>
>>> except NO_INDEX_OR_WHATEVER_THE_EX_IS, e:
>>> sys.stderr.write (_("Microroot for service %s " +
>>> "not in vfstab.\n") % service.serviceName)
>>>
>>>
>>> (Ideally, I would have like to have seen the caller not
>>> need to handle the idx at all, but I won't push for that
>>> at this point.)
>>
>> Dude, I can't make it magically delete things, one has to tell it what you
>> want to delete. How else would one specify what to delete? This is a list
>> after all, not an associative array (aka dictionary) as otherwise the
>> DBFile would have to have knowledge of what columns contain unique data and
>> which can have repeated data.
>>
>
> That's part of the point. Why should the caller need to know if the
> vfstabObj is a list or an array? Secondly, your current implementation
> has the caller extracting something from the object, just to pass it
> back into the object. That something is the idx in this case, and
> there doesn't seem to be any value or meaning for the caller to
> ever have to handle that. So my hinted suggestion was to build a
> member function for the object to hide that detail. For example,
> the caller code could end up looking like this:
>
> try:
> vfstabObj.delentry_by_mntpnt(boot_archive)
>
> # or if we want to parameterize the field out ...
> # (this is probably not correct python syntax, but I know
> # its possible somehow.)
> # vfstabObj.delentry(com.VFSTAB.fields.MOUNT_POINT, boot_archive)
>
> except (ValueError, IndexError):
>
> except IOError, e:
>
> except Whatever Else:
>
>
> Is this over java-fying the code?
Yes, I think this is why Python is different than Java :)
I think this why Python implements the type() function. This is how the
class is implemented modeling a list.
Certainly, we could at the cost of losing a lot of generalization and
adding more code implement something which is very vfstab specific.
But, that's how I see it...
> Lastly, as I noted in the original comment, this is not something
> I am not pushing for this in this putback, but since you're asking
> I'm just clarifying what my comment was.
Cool, thank you for clarifying. I was very confused how, in Python, we
could implement something cleaner. I think as you well put it, the answer
isn't a very Pythonic approach likely -- or at least not very general.
Perhaps a vfstab_obj.del.<field>("key to delete") would be a possible
approach which would be extensible?
> Based on Jan's comment and your filing of 11537, the vfstab
> looks like it may be handled differently altogether in our AI
> server tools, correct?
>
>
>>
>>> 453 - This doesn't look correct. The manpage for in.tftpd
>>> does not say that 'homedir' is the argument to the -s
>>> option. In fact, based on the synopsis, it looks like
>>> 'homedir' can float.
>>>
>>> SYNOPSIS
>>> in.tftpd [-d] [-T rexmtval] [-s] [homedir]
>>>
>>>
>>> So it seems you have to parse fields.SERVER_ARGUMENTS,
>>> looking for the argument that's not an option, and not
>>> an option argument.
>>
>> Thank you for catching this! I've fixed it to take the last argument --
>> much easier to parse out too.
>
> Did you check whether or not the [homedir] argument can float?
> Based on the synopsis, [homedir] looks like it can be put anywhere
> in the command line, not necessarily always at the end. Can you
> verify whether or not this is the case?
I did and I can't do, for example, '/usr/sbin/in.tftpd /tftpboot -d'.
Further, I check that what I get is an absolute path (not to be confused
with rexmtval (which is a numeric value).
>>
>>> 474-478 - I really think we should leave it up to the caller
>>> to check this, so that the interface of findTFTProot()
>>> is defined as always to return something, with the default
>>> being /tftpboot
>>>
>>> (Looking ahead at your code, the callers already do this
>>> checking)
>>
>> Actually this is broken both ways. The callers try to build a path off an
>> unset baseDir variable. I added a meaningful error for the user that we
>> can't do much deleting without a TFTProot (this egregious enough I'm
>> tempted to do a SystemExit, but right now I've added the following checks
>> after line 501:
>> else:
>> sys.stderr.write (_("Unable to remove the grub executable, boot "+
>> "archive, or menu.lst file\nwithout a valid "+
>> "tftp root directory.\n"))
>
>
> Okay, that's fine.
>
> Comment on new delete_service.py file:
> 471-473 - Can you update this error message to be more clear?
> I couldn't tell from the message that something doesn't exist.
> Here's a suggested rewrite of the comment
>
> "The tftp root directory (%s) found from the configuration
> file (%s) does not exist. Using default: %s\n"
Done
> 482-483 - Same comment.
>
> "The tftp root directory (%s) does not exist.\n"
Done
>>
>>
>>> 500-501, 688-689 - Umm, can you please make findTFTProot()
>>> cache its answer then. The chances of someone changing
>>> /etc/inetd.conf in between time is negligible afaic.
>>>
>>> And actually, if you do my previously suggested comment,
>>> you can remove the if()'s at 500 and 688.
>>
>> As the inetd class will be caching the data this is trivial in code
>> runtime. And not easily coded (as findTFTProot is a function not a class)
>> further 500-501, 688-689 are in different scopes (well one's a nested
>> function of the other but that would be very ugly to understand where those
>> vars are coming from to get it to persist). If you think this will save
>> more than 500ms off the runtime of this program I'll profile it to see but
>> this is trivial and very over-optimizing to concern ourselves with.
>
> Since you're not taking my original comment for 474-478 above,
> nevermind this comment.
>
>>
>>>
>>> usr/src/cmd/installadm/delete_client.py
>>> ---------------------------------------
>>> 41 - this comment isn't needed anymore.
>>
>> I've changed from:
>> "Parse and validate options when called as delete-client"
>> to:
>> "Parse and validate options"
>>
>> and for further concern I've changed from parse_client_options to
>> parse_options.
>
> Okay thanks.
>
>>
>> Please I'd like to stop working on nits and ensure the program works this
>> has been out for code review for greater than nearly a month.
>
> You've got a large amount of delta here for the differential though.
> You can't expect to make this much change again and not get an
> initial-like review for the parts that are freshly written.
That is true, just want to be done; we're getting close!
>>
>>> 43 - is this comment still accurate?
>>
>> It is, but perhaps changing service to client would cause less confusion as
>> it returns a client_Data class
>
> That would be a good start.
Done
> thanks,
> -ethan