Skip to content

Allow continuation of verbosity level - #663

Merged
sigmavirus24 merged 4 commits into
PyCQA:masterfrom
mjsir911:merge
Nov 18, 2017
Merged

Allow continuation of verbosity level#663
sigmavirus24 merged 4 commits into
PyCQA:masterfrom
mjsir911:merge

Conversation

@mjsir911

@mjsir911 mjsir911 commented Jul 9, 2017

Copy link
Copy Markdown
Contributor

I've been having to do pycodestyle.StyleGuide(verbose=True, paths=['-v']) to achieve verbosity to the point where I can see the configuration files included such as:

user configuration: /home/mjsir911/.config/pycodestyle
cli configuration: setup.cfg

This simply allows pycodestyle.StyleGuide(verbose=True) to display these verbosity messages.

@IanLee1521 IanLee1521 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks fine to me overall.

One question is hat I'm a little unsure what your comment in line 2284 means... could you clarify?

Comment thread pycodestyle.py Outdated
(options, args) = parser.parse_args(arglist)
options.reporter = None

if verbose: # If specified verbose, continue on verbosity

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is necessary, nor do I think the addition to the signature on 2260 is necessary I'll explain in a different comment. This, however, does not help someone who is trying to pass verbose=False directly meaning that this feature is a bit half-baked.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you suggest alternatively having the keyword argument default to verbose=None, and just check like this?

if verbose is not None:
    options.verbose = verbose

Comment thread pycodestyle.py Outdated
# build options from dict
options_dict = dict(*args, **kwargs)
arglist = None if parse_argv else options_dict.get('paths', None)
verbose = options_dict.get('verbose', False)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we allow verbose to be in the options dictionary, yes? If it is, it was passed here explicitly. Otherwise, (in the case where someone isn't directly using the StyleGuide but is instead using the CLI) we'll parse it from the arguments. Below here, we do options.__dict__.update(options_dict) which means that after we've processed options, we update the values unconditionally so long as options_dict isn't an empty dictionary. That's all you should need.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused, what is the change you are suggesting I make?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, in your use case, you are going to do:

StyleGuide(verbose=True)

Which means that options_dict will look at least like {'verbose': True}. After we call process_options on L1999,L2000 we say if options_dict: options.__dict__.update(options_dict) which means that regardless of what's passed on the CLI we will set verbose to True. That means that you don't need to modify process_options.

I suspect the problem you're actually encountering and trying to solve by this PR is that everything in pycodestyle expects verbose to be an integer. See, as one example, this line:

if verbose >= 3:

If you're not seeing the output you expect when using the Python API, it's because True is being treated as 1 by Python and you're only getting basic verbosity levels.

~ ❯❯❯ python -c 'print(True + 1)'
2
~ ❯❯❯ python3 -c 'print(True + 1)'
2
~ ❯❯❯ python -c 'print(True >= 1)'
True
~ ❯❯❯ python -c 'print(True >= 2)'
False

@mjsir911 mjsir911 Oct 22, 2017

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not know that the verbose is meant to be a number, so I've changed that accordingly.

I do need to modify process_options somehow due to the fact that process_options calls read_config

options = read_config(options, args, arglist, parser)

And read_config checks for options.verbose

pycodestyle/pycodestyle.py

Lines 2251 to 2252 in 19e85d9

if options.verbose:
print('user configuration: %s' % USER_CONFIG)

Which does not get set until L1999 & L2000, after read_config is called, unless you instantiate StyleGuide(paths=['-v']), which does set options.verbose to 1.

I do not think it makes sense to have to pass a CLI argument to the styleguide object to achieve full verbosity, as that is what the verbose argument is for.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I think you had mentioned this before. Thank you for reminding me.

So then the changes necessary here are the following:

verbose = options_dict.pop('verbose', 0)

Then below pass it to process_options as you are. You can make the change there of having verbose=None in the argument list and only if verbose is not None will you set it on the options object.

I think a better path forward, however, is to refactor pycodestyle and remove config reading from CLI argument processing but that's not for this PR.

@sigmavirus24

Copy link
Copy Markdown
Member

Hi @mjsir911

Do you have any intentions to fix this up?

@mjsir911

Copy link
Copy Markdown
Contributor Author

Sorry I haven't touched this PR, will start addressing concerns.

@sigmavirus24 sigmavirus24 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me know if you have any questions. I think you're 90% of the way to a correct solution here.

Comment thread pycodestyle.py Outdated
# build options from dict
options_dict = dict(*args, **kwargs)
arglist = None if parse_argv else options_dict.get('paths', None)
verbose = options_dict.get('verbose', False)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I think you had mentioned this before. Thank you for reminding me.

So then the changes necessary here are the following:

verbose = options_dict.pop('verbose', 0)

Then below pass it to process_options as you are. You can make the change there of having verbose=None in the argument list and only if verbose is not None will you set it on the options object.

I think a better path forward, however, is to refactor pycodestyle and remove config reading from CLI argument processing but that's not for this PR.

@sigmavirus24 sigmavirus24 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One last item.

Comment thread pycodestyle.py Outdated
options_dict = dict(*args, **kwargs)
arglist = None if parse_argv else options_dict.get('paths', None)
verbose = options_dict.get('verbose', False)
verbose = options_dict.get('verbose', 0)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I just realized, having the default of 0 here means we always override options.verbose to 0 even when it's not used via the API. So we can just do options_dict.pop('verbose', None). And yes, we want pop.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pop will not work because at the end of read_config, options is overwritten with command line arguments, which means if -v was not passed somehow it would default to 0.

pycodestyle/pycodestyle.py

Lines 2303 to 2304 in 6faef2b

# Third, overwrite with the command-line options
(options, __) = parser.parse_args(arglist, values=new_options)

This problem has not been apparent because as you pointed out earlier, options_dict gets copied to options.__dict__, but if I pop the verbose key, will not get copied.

Alternatively, (options, __) = parser.parse_args(arglist, values=options) seems to work, but I'm not sure why the previous values=new_options was done the way it was.

Comment thread pycodestyle.py
options_dict = dict(*args, **kwargs)
arglist = None if parse_argv else options_dict.get('paths', None)
verbose = options_dict.get('verbose', 0)
verbose = options_dict.get('verbose', None)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use dict.pop.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pop will not work because at the end of read_config, options is overwritten with command line arguments, which means if -v was not passed somehow it would default to 0.

pycodestyle/pycodestyle.py

Lines 2303 to 2304 in 6faef2b

# Third, overwrite with the command-line options
(options, __) = parser.parse_args(arglist, values=new_options)

This problem has not been apparent because as you pointed out earlier, options_dict gets copied to options.__dict__, but if I pop the verbose key, will not get copied.

Alternatively, (options, __) = parser.parse_args(arglist, values=options) seems to work, but I'm not sure why the previous values=new_options was done the way it was.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing that out. I missed that.

So if you look at the loop that builds up new_options it's pulling in values from config files. But in the chain of preferences, we always want CLI arguments to override those. This is why we one last time do parser.parse_args(arglist, values=new_options). We want to default to what's in the config file, and override those values with what's provided on the CLI.

@sigmavirus24
sigmavirus24 merged commit c631809 into PyCQA:master Nov 18, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants