Some cleanups in 'api' branch

Review Request #2400 — Created June 15, 2011 and submitted

Information

RBTools

Reviewers

The patch fixes very basic issues of 'api' branch enough to make rb-create work. Also new config parser was implemented for rb-config using 'optparse' module.
Tested by hand and eyes.
Description From Last Updated

This won't work for Windows.

chipx86chipx86

Need to use os.path.join() to build paths.

chipx86chipx86

Blank line between these.

chipx86chipx86

Can't use the "as" form.

chipx86chipx86

Can you switch this to using Python format strings while you're at it? It'll be important for localization later.

chipx86chipx86

Here too.

chipx86chipx86

Should only be indented 4 spaces, relative to "values." The trailing } should be aligned with "values".

chipx86chipx86

"Filter out the values that are None."

chipx86chipx86

No space after "[" and before "]".

chipx86chipx86

Blank line before this. You can just do: if valid:

chipx86chipx86

You can just do: for name, value in valid:

chipx86chipx86

Blank line between these.

chipx86chipx86

These won't work with Python 2.4. It should stay how it was. Same with the ones below. Isn't this a …

chipx86chipx86

Not sure I understand this documentation. How about just "First load global options, and then local options. Also, proper capitalization.

mike_conleymike_conley

Needs proper capitalization.

mike_conleymike_conley

I think some quick documentation on what each of these methods tests would be fantastic. :)

mike_conleymike_conley

See above, re single block quote. Maybe for this, you can put: """Tests that we can set arbitrary attributes on …

mike_conleymike_conley

Some documentation would be great here, as well as in the class methods.

mike_conleymike_conley

Space before the if block

mike_conleymike_conley

Needs documentation - just a quick sentence on what this class does. If you could toss in some documentation for …

mike_conleymike_conley

Blank line after this.

chipx86chipx86

No need for \

chipx86chipx86

Blank line after this.

chipx86chipx86

Should use super.

chipx86chipx86

Should use sentence casing, and have a period.

chipx86chipx86

Blank line between these.

chipx86chipx86

Blank line between these.

chipx86chipx86

Blank line between these.

chipx86chipx86

No need for parens. Blank line after this.

chipx86chipx86

Blank line between these.

chipx86chipx86

Only one space after import.

chipx86chipx86

Needs to be one line, and should be short.

chipx86chipx86

No blank line here.

chipx86chipx86

Didn't think we still had this. Or we shouldn't anyway. Like the SCMClients, it should import straight from the module …

chipx86chipx86

assertRegexpMatches isn't in Python 2.4.

chipx86chipx86

Can't depend on with. It's only in newer Pythons than we support.

chipx86chipx86

No blank line here.

chipx86chipx86

Should be two blank lines here.

chipx86chipx86

Indentation is broken.

chipx86chipx86

Probably didn't mean to leave this in?

chipx86chipx86

This seems... Very weird. Can't it just be: for name in opts: uuid = self.gen_uuid() args.append(...) ...

chipx86chipx86

Should probably use parens.

chipx86chipx86

Should use parens.

chipx86chipx86

Should use parens.

chipx86chipx86

If this is going to be used by code outside of this class, it should be a public function (no …

chipx86chipx86

Should use parens.

chipx86chipx86

This would actually be better as a pre-compiled regex constant as part of the class, like: DATE_RE = re.compile(r'....') ... …

chipx86chipx86

Are these intended to be in this change?

chipx86chipx86

Should be "accessed".

mike_conleymike_conley

Space after #, and capitalize first letter of first word. Same for comments below.

mike_conleymike_conley

I'm not 100% sure we need this success variable. The only time it's ever used, it's guaranteed to be True. …

mike_conleymike_conley

Wait - hold up, why can't we commit?

mike_conleymike_conley

Linebreaks before and after this if block.

mike_conleymike_conley

Linebreak after this else block

mike_conleymike_conley

Linebreak before this if-block

mike_conleymike_conley

Linebreak after this if block

mike_conleymike_conley

print isn't a function, and unlike if statements, we tend to just use \ print "No supported ".... \ "supplied …

chipx86chipx86

The compile should be a constant on the class, like: DATE_RE = re.compile(...) Also, "compile," not "complie".

chipx86chipx86

This isn't part of your original change, but while you're here, "json" is only on Python 2.6. So instead, do: …

chipx86chipx86
chipx86
  1. 
      
  2. rbtools/api/settings.py (Diff revision 1)
     
     
    This won't work for Windows.
  3. rbtools/api/settings.py (Diff revision 1)
     
     
     
    Need to use os.path.join() to build paths.
  4. rbtools/api/settings.py (Diff revision 1)
     
     
     
    Blank line between these.
  5. rbtools/api/settings.py (Diff revision 1)
     
     
    Can't use the "as" form.
  6. rbtools/api/settings.py (Diff revision 1)
     
     
     
    Can you switch this to using Python format strings while you're at it? It'll be important for localization later.
  7. rbtools/api/settings.py (Diff revision 1)
     
     
     
    Here too.
  8. rbtools/commands/rbconfig.py (Diff revision 1)
     
     
     
     
     
     
    Should only be indented 4 spaces, relative to "values."
    
    The trailing } should be aligned with "values".
  9. rbtools/commands/rbconfig.py (Diff revision 1)
     
     
    "Filter out the values that are None."
  10. rbtools/commands/rbconfig.py (Diff revision 1)
     
     
    No space after "[" and before "]".
  11. rbtools/commands/rbconfig.py (Diff revision 1)
     
     
    Blank line before this.
    
    You can just do:
    
        if valid:
  12. rbtools/commands/rbconfig.py (Diff revision 1)
     
     
     
    You can just do:
    
        for name, value in valid:
  13. rbtools/commands/rbconfig.py (Diff revision 1)
     
     
     
    Blank line between these.
  14. rbtools/postreview.py (Diff revision 1)
     
     
    These won't work with Python 2.4. It should stay how it was. Same with the ones below.
    
    Isn't this a 3.0 thing?
  15. 
      
MB
mike_conley
  1. Alexander:
    
    Hey - this patch appears to be broken.  Can you try updating it?
    
    Thanks,
    
    -Mike
  2. 
      
MB
MB
JJ
  1. 
      
  2. rbtools/api/settings.py (Diff revision 4)
     
     
    Where are the call sites of these methods you're removing?  Are there none?
    
    By the way, I can't see the branch you refer to on github.  Is it on a fork?  Which one?  What is the branch for?
    1. I was looking at the wrong repo :-/ (I looked at reviewboard instead of rbtools).  The purpose of the branch is clear from the git history, now that I found it :-)
      
      Finding the source code sorted out the call site issue too, so you can ignore that too.  Sorry for the noise.
    2. I was looking at the wrong repo :-/ (I looked at reviewboard instead of rbtools).  The purpose of the branch is clear from the git history, now that I found it :-)
      
      Finding the source code resolved the call site issue too, so you can ignore that too.  Sorry for the noise.
    3. 
       
    4. OK, found the branch (I was looking at reviewboard, not rbtools).  That answers my question about call sites too.  Sorry for the noise!
      
      (BTW, there's some sort of JS bug affecting comments -- I got a duplicate comment rendered, and each comment has two edit buttons.  When I deleted one of the comments, the other one got deleted too :-( )
      
    5. :-/
      
      I had multiple tabs open.  Evidently that results in weird behaviour...
      
  3. rbtools/api/settings.py (Diff revision 4)
     
     
     
     
    If you pass in the config file paths rather than putting this code in the constructor, the tests don't need to rely on the current working directory (nor on conventions about cwd, ~, etc. that might change over time and aren't relevant to most of the tests).
    
    If you want to test that the current working directory is used as a default, you can test that separately in a single test.  Since it's nice to have the minimal amount of code possible depend on such global state, it might be better to move the getcwd() call out of this class (especially since that could change).
    
    Nice talk about this:
    
    http://www.youtube.com/watch?v=-FRm3VPhseI
    1. I'll add load(config_name) later in order to let third-parties to load whatever they want.
  4. rbtools/commands/resource-browser.py (Diff revision 4)
     
     
    Every time you make a Settings object you immediately call .load on it -- except here.  Is that a mistake?
    
    Why not just let Settings load when it needs to (e.g. in the constructor)?
    
    1. I didn't work in this module, and probably won't do. We plan GUI implementation with Tkinter.
    2. I didn't work resource-browser and probably won't do. We plan to implement GUI with Tkinter. Also putting 'load()' into constructor is likely to be a side-effect.
  5. rbtools/testutils.py (Diff revision 4)
     
     
     
    It's nice that this is an explicit method rather than ad-hoc code in the tests.
    
    It would be even better if it cleaned up at the end of the test case (by removing the temporary directory -- and chdir-ing back to the original cwd, if the chdir is really necessary).  The same goes for the other methods here that touch global state.  One nice way to do that is to implement these using a method similar to unittest2's .addCleanup().
    
    Here's a really simple implementation of that idea:
    
    http://lackingrhoticity.blogspot.com/2008/11/tempdirtestcase-python-unittest-helper.html
    
  6. 
      
JJ
  1. 
      
  2. rbtools/api/utilities.py (Diff revision 4)
     
     
    Dead code?
    1. no, see make_tempfile
  3. rbtools/commands/rbconfig.py (Diff revision 4)
     
     
    Since you're cleaning this up, maybe add a usage string to say what the program does?
    1. There is '-h'/'--help' option support built-in optparse module. Just run `rb config -h' and you'll see.
  4. rbtools/commands/rbconfig.py (Diff revision 4)
     
     
    Isn't it "Review Board", not "ReviewBoard"?
    
    (I don't know for sure)
    1. I'm sure too, but for sure it is not so important and can be changed later.
  5. rbtools/commands/rbconfig.py (Diff revision 4)
     
     
    Needs a help string.
  6. rbtools/commands/rbconfig.py (Diff revision 4)
     
     
    Why not make the option dest the same as the config file here?  It seems confusing to present the user with two names for the same setting.
    
    If you do that, you can use optparse.make_option (and the .dest attribute of optparse.Option), which would allow eliminating the repetition of the dest values.
    1. I think I don't understand your idea. The legacy option name (the one postreview uses) is 'reviewboard_url', so I left it untouched.
  7. rbtools/commands/rbconfig.py (Diff revision 4)
     
     
    Use "is not None", not "!= None"
  8. rbtools/commands/rbconfig.py (Diff revision 4)
     
     
    If it's going to print anything at all on success, maybe move this to after the setattr and have it print something that explicitly says what it has done, e.g. "Set %s : %s"?
  9. rbtools/commands/rbconfig.py (Diff revision 4)
     
     
    This isn't very helpful to the user:
    
    $ rb config
    
    Usage: rb config [options]
    
    
    Maybe print_help() instead?
  10. rbtools/commands/rbcreate.py (Diff revision 4)
     
     
     
    This is a no-op, right?  Delete the try/except?
    1. I just fix the invalid name for exception super-class, will work in this module later.
  11. 
      
MB
mike_conley
  1. Alexander:
    
    This is looking really solid to me!  Just a few nits, and some documentation requests.  Thanks,
    
    -Mike
  2. rbtools/api/settings.py (Diff revision 5)
     
     
    typo:  "<name> is a valid option" - also, instead of two block quote passages, maybe this could be a single?  See:  https://github.com/reviewboard/reviewboard/blob/b5209aabf67994f8613844fa20dbdd55eab07a87/reviewboard/webapi/resources.py#L810 for example.
    
    Also, please properly capitalize in your documentation.
  3. rbtools/api/settings.py (Diff revision 5)
     
     
    Not sure I understand this documentation.  How about just "First load global options, and then local options.
    
    Also, proper capitalization. 
  4. rbtools/api/settings.py (Diff revision 5)
     
     
    Needs proper capitalization.
  5. rbtools/api/test.py (Diff revision 5)
     
     
    I think some quick documentation on what each of these methods tests would be fantastic. :)
  6. rbtools/api/test.py (Diff revision 5)
     
     
     
    See above, re single block quote.  Maybe for this, you can put:
    
    """Tests that we can set arbitrary attributes on an instance of Settings.
    """
  7. rbtools/api/test.py (Diff revision 5)
     
     
    Some documentation would be great here, as well as in the class methods.
  8. rbtools/commands/rbconfig.py (Diff revision 5)
     
     
    Space before the if block
  9. rbtools/testutils.py (Diff revision 5)
     
     
    Needs documentation - just a quick sentence on what this class does.  If you could toss in some documentation for the methods as well, that'd be awesome. :)
  10. 
      
MB
chipx86
  1. So there's a number of specific style comments, but I have a few main points:
    
    1) This seems to use a lot of old code (RBUtilities, for example) instead of the newer modules that you put into place with the SCMClients change. It doesn't look like it's merged with master?
    
    2) I'm concerned this change is doing too much. It's fixing style issues, modifying stuff in SCMClients, adding a whole new settings framework, adding unit tests, adding unrelated TODOs (for git). It's the perfect example of a change that should be split up.
    
    I'd advise splitting up the settings stuff into its own change, after fixing the things below, and having another change solely for the style changes and comment additions.
    
    I'd also advise having a change just for the new unit test utils.
    
    I know that seems like extra work when you already have it all written, but we're going to have to get things in little by little, and when you have a really large change and we notice a regression or problem down the line, it makes it far more difficult to track it. Bite-sized changes that implement one thing are way easier all around.
    
    As a more general comment, if a change can be put onto master (style changes, maybe unit test utils), it'd be good to target it there instead of api. That results in less we end up merging in from api, making that easier to maintain as well.
  2. .reviewboardrc (Diff revision 6)
     
     
    Important note: This can't be required, or we'll break a *lot* of companies. I don't know how ConfigParser works, but if it absolutely has to have an INI section header, we can't use it here. Actually, come to think of it, we can't use ConfigParser. We need the .reviewboardrc files to work as they always have been. That is, they need to be essentially Python scripts. Many companies depend on them to be executable in order to fix up proxy issues and stuff. So that can't change.
  3. rbtools/api/settings.py (Diff revision 6)
     
     
    Blank line after this.
  4. rbtools/api/settings.py (Diff revision 6)
     
     
    No need for \
  5. rbtools/api/settings.py (Diff revision 6)
     
     
    Blank line after this.
  6. rbtools/api/settings.py (Diff revision 6)
     
     
    Should use super.
  7. rbtools/api/settings.py (Diff revision 6)
     
     
     
    Should use sentence casing, and have a period.
  8. rbtools/api/settings.py (Diff revision 6)
     
     
     
    Blank line between these.
  9. rbtools/api/settings.py (Diff revision 6)
     
     
     
    Blank line between these.
  10. rbtools/api/settings.py (Diff revision 6)
     
     
     
    Blank line between these.
  11. rbtools/api/settings.py (Diff revision 6)
     
     
    No need for parens.
    
    Blank line after this.
  12. rbtools/api/settings.py (Diff revision 6)
     
     
     
    Blank line between these.
  13. rbtools/api/test.py (Diff revision 6)
     
     
    Only one space after import.
  14. rbtools/api/test.py (Diff revision 6)
     
     
     
    Needs to be one line, and should be short.
  15. rbtools/api/test.py (Diff revision 6)
     
     
     
     
    No blank line here.
  16. rbtools/api/test.py (Diff revision 6)
     
     
    Didn't think we still had this. Or we shouldn't anyway. Like the SCMClients, it should import straight from the module it's in.
    
    Same with all other instances.
  17. rbtools/api/test.py (Diff revision 6)
     
     
    assertRegexpMatches isn't in Python 2.4.
  18. rbtools/api/test.py (Diff revision 6)
     
     
    Can't depend on with. It's only in newer Pythons than we support.
  19. rbtools/api/utilities.py (Diff revision 6)
     
     
     
    No blank line here.
  20. rbtools/api/utilities.py (Diff revision 6)
     
     
     
     
    Should be two blank lines here.
  21. rbtools/api/utilities.py (Diff revision 6)
     
     
     
     
     
    Indentation is broken.
  22. rbtools/commands/rbconfig.py (Diff revision 6)
     
     
    Probably didn't mean to leave this in?
  23. rbtools/commands/test.py (Diff revision 6)
     
     
    This seems... Very weird. Can't it just be:
    
    for name in opts:
        uuid = self.gen_uuid()
        args.append(...)
        ...
  24. 
      
MB
DH
  1. 
      
  2. 
      
chipx86
  1. Can you explain some of the motivation for this change?  Why the change from utils to util? And files to fs?
    
    It seems like there are things in here that probably weren't supposed to be part of this review request.
    1. I noticed that the most of built-in modules and many third-party have singular names. So I thought it would be good to stick this strategy. The name 'files' seamed odd for me when I looked through that file again. So 'fs' (stands for 'filesystem') I thought would be more accurate.
  2. rbtools/clients/git.py (Diff revision 7)
     
     
     
     
    Should probably use parens.
  3. rbtools/clients/git.py (Diff revision 7)
     
     
     
    Should use parens.
  4. rbtools/clients/git.py (Diff revision 7)
     
     
     
    Should use parens.
  5. rbtools/clients/git.py (Diff revision 7)
     
     
    If this is going to be used by code outside of this class, it should be a public function (no _ prefix), and shouldn't be "internal."
    
    However, this seems to be something that should be in a different review request, since it's not really cleanup, is it?
    1. This is virtual method and is also presented in SCMClient. Probably it appeared here because was accidentally removed from 'api', as I came across this method at merging my branch (that was branched from 'api') with new upstream/api.
  6. rbtools/clients/perforce.py (Diff revision 7)
     
     
     
    Should use parens.
  7. rbtools/clients/perforce.py (Diff revision 7)
     
     
    This would actually be better as a pre-compiled regex constant as part of the class, like:
    
    DATE_RE = re.compile(r'....')
    
    ...
    
    m = self.DATE_RE.search(dl[1])
  8. rbtools/commands/rbclose.py (Diff revision 7)
     
     
     
    Are these intended to be in this change?
  9. 
      
MB
mike_conley
  1. Alexander:
    
    This looks pretty good!  I agree with Christian, however - this change should probably be broken up into two or more diffs.  I've noticed that some changes are purely cosmetic / stylistic (cleaning whitespace, reducing lines to <= 80 chars), while other changes have deeper potential impacts (renaming, new code, etc).  Maybe you can split along those lines.
    
    All the best,
    
    -Mike
  2. rbtools/clients/__init__.py (Diff revision 8)
     
     
    Should be "accessed".
  3. rbtools/clients/git.py (Diff revision 8)
     
     
    Space after #, and capitalize first letter of first word.  Same for comments below.
  4. rbtools/clients/git.py (Diff revision 8)
     
     
    I'm not 100% sure we need this success variable.
    
    The only time it's ever used, it's guaranteed to be True.
    
    I think the var can be dropped, and just return true on line 410.
  5. rbtools/clients/git.py (Diff revision 8)
     
     
    Wait - hold up, why can't we commit?
  6. rbtools/util/fs.py (Diff revision 8)
     
     
     
    Linebreaks before and after this if block.
  7. rbtools/util/process.py (Diff revision 8)
     
     
    Linebreak after this else block
  8. rbtools/util/process.py (Diff revision 8)
     
     
    Linebreak before this if-block
  9. 
      
MB
mike_conley
  1. Except for the one issue below, this looks pretty good to me.
  2. rbtools/utils/filesystem.py (Diff revision 9)
     
     
    Linebreak after this if block
  3. 
      
MB
MB
chipx86
  1. Just about there! One small style things, and a couple critical problems.
  2. rbtools/clients/__init__.py (Diff revision 11)
     
     
     
    print isn't a function, and unlike if statements, we tend to just use \
    
    print "No supported ".... \
          "supplied url."
    
    (Always break on full words.)
  3. rbtools/clients/perforce.py (Diff revision 11)
     
     
    The compile should be a constant on the class, like:
    
    DATE_RE = re.compile(...)
    
    Also, "compile," not "complie".
  4. rbtools/commands/utils.py (Diff revision 11)
     
     
    This isn't part of your original change, but while you're here, "json" is only on Python 2.6. So instead, do:
    
    try:
        from json import dumps
    except ImportError:
        from simplejson import dumps
  5. 
      
MB
chipx86
  1. Ship It!
  2. 
      
MB
Review request changed

Status: Closed (submitted)

Change Summary:

Committed to api (a69afbc)
Loading...