This change removes the `.config_finder` object from the `Application`.
Since the configuration finder is only needed during initialization, we
constrain the finder to be returned and passed to other methods
necessary for initialization.
Positional arguments aren't necessary for determining where to
load configuration anymore and is safe to keep both options and
arguments to be forwarded for later parsing after configuration is
loaded.
Now that preliminary options are registered with the preliminary parser
on the `Application`, leverage that for parsing known options.
This important change removes the `Application.option_manager` from
being responsible for pre-configuration parsing and the workarounds
needed in the `Application.parse_preliminary_options_and_args()` to
account for the fact that `Application.option_manager` was aware of
*all* options, not just the options necessary for pre-configuration
loading. A following commit will address removing these workarounds.
We introduce a new `ArgumentParser` for registering the preliminary
options to be inherited by the `Application.option_manager`. The next
step will be to use the `Application.prelim_arg_parser` for parsing and
handling preliminary options and arguments.
Note that we prevent the preliminary parser from handling `-h/--help`
and defer to that to the primary parser.
Allow for including options from parent `argparse.ArgumentParser`
objects in preparation of splitting out the handling of preliminary
options from the `OptionManager`.
The `ConfigFileFinder` doesn't utilize the preliminary arguments (i.e.,
the file names) anymore for computing the starting path for the
configuration file search.
Now that `args` parameters is not being used, it is safe to remove from
the constructor signature.
Further work is required to evaluate and clean-up tearing out the
threading-through of `args` from various callers and tests.
The `--verbose` option is only used by `flake8`, itself,` when parsing
and handling preliminary options. After parsing and merging options
from the configuration file, there is no other behavioral impact to the
core of `flake8`. In other words, setting `verbose = ...` in a
configuration file doesn't change the logging verbosity.
While the `FileProcessor` does expose a `verbose` attribute, obtained
from the parsed options, the verbosity of the core of `flake8` should be
consistent with how a plugin may respond to the attribute's value.
The preliminary options and arguments returned from
`.parse_preliminary_options_and_args()` are now all threaded through to
the appropriate methods during initialization.
The configuration file and boolean to ignore configuration files can be
threaded through now that `.parse_preliminary_options_and_args()`
returns options and arguments.
Now that `.parse_preliminary_options_and_args()` returns options and
arguments, the boolean for appending configuration and the arguments can
be threaded through to the creation of the `ConfigFileFinder`.
The verbosity and output file options can be obtained from options
returned by `.parse_preliminary_options_and_args()`, instead of state
from the `Application` object.
This is the initial step towards removing state from the `Application`
object during argument parsing and handling. The goal is to remove
`Application.prelim_opts` and `Application.prelim_args`.
When calling `ArgumentParser.parse_args()` with the `namespace`
argument, command-line options are just added to the namespace without
going through any of the argument parsing and type conversion logic
(e.g., the `type` keyword argument of `ArgumentParser.add_argument()`).
In other words, it is assumed that a namespace is well-formed from a
previous invocation of `ArgumentParser.parse_args()`.
The `values` parameter is intended to be values already-provided from
configuration files. To take advantage of the logic defined by
`ArgumentParser.add_argument()`, utilize
`ArgumentParser.set_defaults()` instead.
`flake8.main.cli.main()` is the primary entry point for the command-line
implementation of flake8 (invoked via `__main__` or `console_scripts`).
Therefore, it is reasonable for the entry point to be responsible for
obtaining command line arguments from `sys.argv` there.
Note that `sys.argv[1:]` is necessary in order to strip off the script
name. Formerly, this was not needed in
`Application.parse_preliminary_options_and_args()`, which was using
`sys.argv[:]` because the result of the argument parsing was just for
determining additional configuration to be loaded. Then, the *real* CLI
argument parsing was forwarding the original `None` value to
`argparse.ArgumentParser.parse_args()`, which internally was obtaining
arguments as `sys.argv[1:]`.
Additionally, the contract for various argument parsing methods to be
guaranteed a `List[str]`.
Now that callers are ensuring that `value` is not `None`, we can further
tighten the contract and remove the conditional to account when `None`
is passed-in for `value`.
Additionally, add a new test vector to account for when an empty string
is passed in, which would fail `if no value`.
The `normalize_paths()` utility was doing too much — parsing
unstructured configuration path data and dispatching the scrubbed paths
to be normalized.
Towards moving the parsing of unstructured configuration path data
closer towards were configuration occurs, have the utility accept only
structured input for normalizing paths.