mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-22 23:11:08 -05:00
okay fine
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
"""Package containing the option manager and config management logic.
|
||||
|
||||
- :mod:`flake8.options.config` contains the logic for finding, parsing, and
|
||||
merging configuration files.
|
||||
|
||||
- :mod:`flake8.options.manager` contains the logic for managing customized
|
||||
Flake8 command-line and configuration options.
|
||||
|
||||
- :mod:`flake8.options.aggregator` uses objects from both of the above modules
|
||||
to aggregate configuration into one object used by plugins and Flake8.
|
||||
|
||||
"""
|
||||
from __future__ import annotations
|
||||
@@ -0,0 +1,56 @@
|
||||
"""Aggregation function for CLI specified options and config file options.
|
||||
|
||||
This holds the logic that uses the collected and merged config files and
|
||||
applies the user-specified command-line configuration on top of it.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import configparser
|
||||
import logging
|
||||
from typing import Sequence
|
||||
|
||||
from flake8.options import config
|
||||
from flake8.options.manager import OptionManager
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def aggregate_options(
|
||||
manager: OptionManager,
|
||||
cfg: configparser.RawConfigParser,
|
||||
cfg_dir: str,
|
||||
argv: Sequence[str] | None,
|
||||
) -> argparse.Namespace:
|
||||
"""Aggregate and merge CLI and config file options."""
|
||||
# Get defaults from the option parser
|
||||
default_values = manager.parse_args([])
|
||||
|
||||
# Get the parsed config
|
||||
parsed_config = config.parse_config(manager, cfg, cfg_dir)
|
||||
|
||||
# store the plugin-set extended default ignore / select
|
||||
default_values.extended_default_ignore = manager.extended_default_ignore
|
||||
default_values.extended_default_select = manager.extended_default_select
|
||||
|
||||
# Merge values parsed from config onto the default values returned
|
||||
for config_name, value in parsed_config.items():
|
||||
dest_name = config_name
|
||||
# If the config name is somehow different from the destination name,
|
||||
# fetch the destination name from our Option
|
||||
if not hasattr(default_values, config_name):
|
||||
dest_val = manager.config_options_dict[config_name].dest
|
||||
assert isinstance(dest_val, str)
|
||||
dest_name = dest_val
|
||||
|
||||
LOG.debug(
|
||||
'Overriding default value of (%s) for "%s" with (%s)',
|
||||
getattr(default_values, dest_name, None),
|
||||
dest_name,
|
||||
value,
|
||||
)
|
||||
# Override the default values with the config values
|
||||
setattr(default_values, dest_name, value)
|
||||
|
||||
# Finally parse the command-line options
|
||||
return manager.parse_args(argv, default_values)
|
||||
140
.venv/lib/python3.12/site-packages/flake8/options/config.py
Normal file
140
.venv/lib/python3.12/site-packages/flake8/options/config.py
Normal file
@@ -0,0 +1,140 @@
|
||||
"""Config handling logic for Flake8."""
|
||||
from __future__ import annotations
|
||||
|
||||
import configparser
|
||||
import logging
|
||||
import os.path
|
||||
from typing import Any
|
||||
|
||||
from flake8 import exceptions
|
||||
from flake8.defaults import VALID_CODE_PREFIX
|
||||
from flake8.options.manager import OptionManager
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _stat_key(s: str) -> tuple[int, int]:
|
||||
# same as what's used by samefile / samestat
|
||||
st = os.stat(s)
|
||||
return st.st_ino, st.st_dev
|
||||
|
||||
|
||||
def _find_config_file(path: str) -> str | None:
|
||||
# on windows if the homedir isn't detected this returns back `~`
|
||||
home = os.path.expanduser("~")
|
||||
try:
|
||||
home_stat = _stat_key(home) if home != "~" else None
|
||||
except OSError: # FileNotFoundError / PermissionError / etc.
|
||||
home_stat = None
|
||||
|
||||
dir_stat = _stat_key(path)
|
||||
while True:
|
||||
for candidate in ("setup.cfg", "tox.ini", ".flake8"):
|
||||
cfg = configparser.RawConfigParser()
|
||||
cfg_path = os.path.join(path, candidate)
|
||||
try:
|
||||
cfg.read(cfg_path, encoding="UTF-8")
|
||||
except (UnicodeDecodeError, configparser.ParsingError) as e:
|
||||
LOG.warning("ignoring unparseable config %s: %s", cfg_path, e)
|
||||
else:
|
||||
# only consider it a config if it contains flake8 sections
|
||||
if "flake8" in cfg or "flake8:local-plugins" in cfg:
|
||||
return cfg_path
|
||||
|
||||
new_path = os.path.dirname(path)
|
||||
new_dir_stat = _stat_key(new_path)
|
||||
if new_dir_stat == dir_stat or new_dir_stat == home_stat:
|
||||
break
|
||||
else:
|
||||
path = new_path
|
||||
dir_stat = new_dir_stat
|
||||
|
||||
# did not find any configuration file
|
||||
return None
|
||||
|
||||
|
||||
def load_config(
|
||||
config: str | None,
|
||||
extra: list[str],
|
||||
*,
|
||||
isolated: bool = False,
|
||||
) -> tuple[configparser.RawConfigParser, str]:
|
||||
"""Load the configuration given the user options.
|
||||
|
||||
- in ``isolated`` mode, return an empty configuration
|
||||
- if a config file is given in ``config`` use that, otherwise attempt to
|
||||
discover a configuration using ``tox.ini`` / ``setup.cfg`` / ``.flake8``
|
||||
- finally, load any ``extra`` configuration files
|
||||
"""
|
||||
pwd = os.path.abspath(".")
|
||||
|
||||
if isolated:
|
||||
return configparser.RawConfigParser(), pwd
|
||||
|
||||
if config is None:
|
||||
config = _find_config_file(pwd)
|
||||
|
||||
cfg = configparser.RawConfigParser()
|
||||
if config is not None:
|
||||
if not cfg.read(config, encoding="UTF-8"):
|
||||
raise exceptions.ExecutionError(
|
||||
f"The specified config file does not exist: {config}"
|
||||
)
|
||||
cfg_dir = os.path.dirname(config)
|
||||
else:
|
||||
cfg_dir = pwd
|
||||
|
||||
# TODO: remove this and replace it with configuration modifying plugins
|
||||
# read the additional configs afterwards
|
||||
for filename in extra:
|
||||
if not cfg.read(filename, encoding="UTF-8"):
|
||||
raise exceptions.ExecutionError(
|
||||
f"The specified config file does not exist: {filename}"
|
||||
)
|
||||
|
||||
return cfg, cfg_dir
|
||||
|
||||
|
||||
def parse_config(
|
||||
option_manager: OptionManager,
|
||||
cfg: configparser.RawConfigParser,
|
||||
cfg_dir: str,
|
||||
) -> dict[str, Any]:
|
||||
"""Parse and normalize the typed configuration options."""
|
||||
if "flake8" not in cfg:
|
||||
return {}
|
||||
|
||||
config_dict = {}
|
||||
|
||||
for option_name in cfg["flake8"]:
|
||||
option = option_manager.config_options_dict.get(option_name)
|
||||
if option is None:
|
||||
LOG.debug('Option "%s" is not registered. Ignoring.', option_name)
|
||||
continue
|
||||
|
||||
# Use the appropriate method to parse the config value
|
||||
value: Any
|
||||
if option.type is int or option.action == "count":
|
||||
value = cfg.getint("flake8", option_name)
|
||||
elif option.action in {"store_true", "store_false"}:
|
||||
value = cfg.getboolean("flake8", option_name)
|
||||
else:
|
||||
value = cfg.get("flake8", option_name)
|
||||
|
||||
LOG.debug('Option "%s" returned value: %r', option_name, value)
|
||||
|
||||
final_value = option.normalize(value, cfg_dir)
|
||||
|
||||
if option_name in {"ignore", "extend-ignore"}:
|
||||
for error_code in final_value:
|
||||
if not VALID_CODE_PREFIX.match(error_code):
|
||||
raise ValueError(
|
||||
f"Error code {error_code!r} "
|
||||
f"supplied to {option_name!r} option "
|
||||
f"does not match {VALID_CODE_PREFIX.pattern!r}"
|
||||
)
|
||||
|
||||
assert option.config_name is not None
|
||||
config_dict[option.config_name] = final_value
|
||||
|
||||
return config_dict
|
||||
320
.venv/lib/python3.12/site-packages/flake8/options/manager.py
Normal file
320
.venv/lib/python3.12/site-packages/flake8/options/manager.py
Normal file
@@ -0,0 +1,320 @@
|
||||
"""Option handling and Option management logic."""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import enum
|
||||
import functools
|
||||
import logging
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import Sequence
|
||||
|
||||
from flake8 import utils
|
||||
from flake8.plugins.finder import Plugins
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
# represent a singleton of "not passed arguments".
|
||||
# an enum is chosen to trick mypy
|
||||
_ARG = enum.Enum("_ARG", "NO")
|
||||
|
||||
|
||||
def _flake8_normalize(
|
||||
value: str,
|
||||
*args: str,
|
||||
comma_separated_list: bool = False,
|
||||
normalize_paths: bool = False,
|
||||
) -> str | list[str]:
|
||||
ret: str | list[str] = value
|
||||
if comma_separated_list and isinstance(ret, str):
|
||||
ret = utils.parse_comma_separated_list(value)
|
||||
|
||||
if normalize_paths:
|
||||
if isinstance(ret, str):
|
||||
ret = utils.normalize_path(ret, *args)
|
||||
else:
|
||||
ret = utils.normalize_paths(ret, *args)
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
class Option:
|
||||
"""Our wrapper around an argparse argument parsers to add features."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
short_option_name: str | _ARG = _ARG.NO,
|
||||
long_option_name: str | _ARG = _ARG.NO,
|
||||
# Options below are taken from argparse.ArgumentParser.add_argument
|
||||
action: str | type[argparse.Action] | _ARG = _ARG.NO,
|
||||
default: Any | _ARG = _ARG.NO,
|
||||
type: Callable[..., Any] | _ARG = _ARG.NO,
|
||||
dest: str | _ARG = _ARG.NO,
|
||||
nargs: int | str | _ARG = _ARG.NO,
|
||||
const: Any | _ARG = _ARG.NO,
|
||||
choices: Sequence[Any] | _ARG = _ARG.NO,
|
||||
help: str | _ARG = _ARG.NO,
|
||||
metavar: str | _ARG = _ARG.NO,
|
||||
required: bool | _ARG = _ARG.NO,
|
||||
# Options below here are specific to Flake8
|
||||
parse_from_config: bool = False,
|
||||
comma_separated_list: bool = False,
|
||||
normalize_paths: bool = False,
|
||||
) -> None:
|
||||
"""Initialize an Option instance.
|
||||
|
||||
The following are all passed directly through to argparse.
|
||||
|
||||
:param short_option_name:
|
||||
The short name of the option (e.g., ``-x``). This will be the
|
||||
first argument passed to ``ArgumentParser.add_argument``
|
||||
:param long_option_name:
|
||||
The long name of the option (e.g., ``--xtra-long-option``). This
|
||||
will be the second argument passed to
|
||||
``ArgumentParser.add_argument``
|
||||
:param default:
|
||||
Default value of the option.
|
||||
:param dest:
|
||||
Attribute name to store parsed option value as.
|
||||
:param nargs:
|
||||
Number of arguments to parse for this option.
|
||||
:param const:
|
||||
Constant value to store on a common destination. Usually used in
|
||||
conjunction with ``action="store_const"``.
|
||||
:param choices:
|
||||
Possible values for the option.
|
||||
:param help:
|
||||
Help text displayed in the usage information.
|
||||
:param metavar:
|
||||
Name to use instead of the long option name for help text.
|
||||
:param required:
|
||||
Whether this option is required or not.
|
||||
|
||||
The following options may be passed directly through to :mod:`argparse`
|
||||
but may need some massaging.
|
||||
|
||||
:param type:
|
||||
A callable to normalize the type (as is the case in
|
||||
:mod:`argparse`).
|
||||
:param action:
|
||||
Any action allowed by :mod:`argparse`.
|
||||
|
||||
The following parameters are for Flake8's option handling alone.
|
||||
|
||||
:param parse_from_config:
|
||||
Whether or not this option should be parsed out of config files.
|
||||
:param comma_separated_list:
|
||||
Whether the option is a comma separated list when parsing from a
|
||||
config file.
|
||||
:param normalize_paths:
|
||||
Whether the option is expecting a path or list of paths and should
|
||||
attempt to normalize the paths to absolute paths.
|
||||
"""
|
||||
if (
|
||||
long_option_name is _ARG.NO
|
||||
and short_option_name is not _ARG.NO
|
||||
and short_option_name.startswith("--")
|
||||
):
|
||||
short_option_name, long_option_name = _ARG.NO, short_option_name
|
||||
|
||||
# flake8 special type normalization
|
||||
if comma_separated_list or normalize_paths:
|
||||
type = functools.partial(
|
||||
_flake8_normalize,
|
||||
comma_separated_list=comma_separated_list,
|
||||
normalize_paths=normalize_paths,
|
||||
)
|
||||
|
||||
self.short_option_name = short_option_name
|
||||
self.long_option_name = long_option_name
|
||||
self.option_args = [
|
||||
x
|
||||
for x in (short_option_name, long_option_name)
|
||||
if x is not _ARG.NO
|
||||
]
|
||||
self.action = action
|
||||
self.default = default
|
||||
self.type = type
|
||||
self.dest = dest
|
||||
self.nargs = nargs
|
||||
self.const = const
|
||||
self.choices = choices
|
||||
self.help = help
|
||||
self.metavar = metavar
|
||||
self.required = required
|
||||
self.option_kwargs: dict[str, Any | _ARG] = {
|
||||
"action": self.action,
|
||||
"default": self.default,
|
||||
"type": self.type,
|
||||
"dest": self.dest,
|
||||
"nargs": self.nargs,
|
||||
"const": self.const,
|
||||
"choices": self.choices,
|
||||
"help": self.help,
|
||||
"metavar": self.metavar,
|
||||
"required": self.required,
|
||||
}
|
||||
|
||||
# Set our custom attributes
|
||||
self.parse_from_config = parse_from_config
|
||||
self.comma_separated_list = comma_separated_list
|
||||
self.normalize_paths = normalize_paths
|
||||
|
||||
self.config_name: str | None = None
|
||||
if parse_from_config:
|
||||
if long_option_name is _ARG.NO:
|
||||
raise ValueError(
|
||||
"When specifying parse_from_config=True, "
|
||||
"a long_option_name must also be specified."
|
||||
)
|
||||
self.config_name = long_option_name[2:].replace("-", "_")
|
||||
|
||||
self._opt = None
|
||||
|
||||
@property
|
||||
def filtered_option_kwargs(self) -> dict[str, Any]:
|
||||
"""Return any actually-specified arguments."""
|
||||
return {
|
||||
k: v for k, v in self.option_kwargs.items() if v is not _ARG.NO
|
||||
}
|
||||
|
||||
def __repr__(self) -> str: # noqa: D105
|
||||
parts = []
|
||||
for arg in self.option_args:
|
||||
parts.append(arg)
|
||||
for k, v in self.filtered_option_kwargs.items():
|
||||
parts.append(f"{k}={v!r}")
|
||||
return f"Option({', '.join(parts)})"
|
||||
|
||||
def normalize(self, value: Any, *normalize_args: str) -> Any:
|
||||
"""Normalize the value based on the option configuration."""
|
||||
if self.comma_separated_list and isinstance(value, str):
|
||||
value = utils.parse_comma_separated_list(value)
|
||||
|
||||
if self.normalize_paths:
|
||||
if isinstance(value, list):
|
||||
value = utils.normalize_paths(value, *normalize_args)
|
||||
else:
|
||||
value = utils.normalize_path(value, *normalize_args)
|
||||
|
||||
return value
|
||||
|
||||
def to_argparse(self) -> tuple[list[str], dict[str, Any]]:
|
||||
"""Convert a Flake8 Option to argparse ``add_argument`` arguments."""
|
||||
return self.option_args, self.filtered_option_kwargs
|
||||
|
||||
|
||||
class OptionManager:
|
||||
"""Manage Options and OptionParser while adding post-processing."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
version: str,
|
||||
plugin_versions: str,
|
||||
parents: list[argparse.ArgumentParser],
|
||||
formatter_names: list[str],
|
||||
) -> None:
|
||||
"""Initialize an instance of an OptionManager."""
|
||||
self.formatter_names = formatter_names
|
||||
self.parser = argparse.ArgumentParser(
|
||||
prog="flake8",
|
||||
usage="%(prog)s [options] file file ...",
|
||||
parents=parents,
|
||||
epilog=f"Installed plugins: {plugin_versions}",
|
||||
)
|
||||
self.parser.add_argument(
|
||||
"--version",
|
||||
action="version",
|
||||
version=(
|
||||
f"{version} ({plugin_versions}) "
|
||||
f"{utils.get_python_version()}"
|
||||
),
|
||||
)
|
||||
self.parser.add_argument("filenames", nargs="*", metavar="filename")
|
||||
|
||||
self.config_options_dict: dict[str, Option] = {}
|
||||
self.options: list[Option] = []
|
||||
self.extended_default_ignore: list[str] = []
|
||||
self.extended_default_select: list[str] = []
|
||||
|
||||
self._current_group: argparse._ArgumentGroup | None = None
|
||||
|
||||
# TODO: maybe make this a free function to reduce api surface area
|
||||
def register_plugins(self, plugins: Plugins) -> None:
|
||||
"""Register the plugin options (if needed)."""
|
||||
groups: dict[str, argparse._ArgumentGroup] = {}
|
||||
|
||||
def _set_group(name: str) -> None:
|
||||
try:
|
||||
self._current_group = groups[name]
|
||||
except KeyError:
|
||||
group = self.parser.add_argument_group(name)
|
||||
self._current_group = groups[name] = group
|
||||
|
||||
for loaded in plugins.all_plugins():
|
||||
add_options = getattr(loaded.obj, "add_options", None)
|
||||
if add_options:
|
||||
_set_group(loaded.plugin.package)
|
||||
add_options(self)
|
||||
|
||||
if loaded.plugin.entry_point.group == "flake8.extension":
|
||||
self.extend_default_select([loaded.entry_name])
|
||||
|
||||
# isn't strictly necessary, but seems cleaner
|
||||
self._current_group = None
|
||||
|
||||
def add_option(self, *args: Any, **kwargs: Any) -> None:
|
||||
"""Create and register a new option.
|
||||
|
||||
See parameters for :class:`~flake8.options.manager.Option` for
|
||||
acceptable arguments to this method.
|
||||
|
||||
.. note::
|
||||
|
||||
``short_option_name`` and ``long_option_name`` may be specified
|
||||
positionally as they are with argparse normally.
|
||||
"""
|
||||
option = Option(*args, **kwargs)
|
||||
option_args, option_kwargs = option.to_argparse()
|
||||
if self._current_group is not None:
|
||||
self._current_group.add_argument(*option_args, **option_kwargs)
|
||||
else:
|
||||
self.parser.add_argument(*option_args, **option_kwargs)
|
||||
self.options.append(option)
|
||||
if option.parse_from_config:
|
||||
name = option.config_name
|
||||
assert name is not None
|
||||
self.config_options_dict[name] = option
|
||||
self.config_options_dict[name.replace("_", "-")] = option
|
||||
LOG.debug('Registered option "%s".', option)
|
||||
|
||||
def extend_default_ignore(self, error_codes: Sequence[str]) -> None:
|
||||
"""Extend the default ignore list with the error codes provided.
|
||||
|
||||
:param error_codes:
|
||||
List of strings that are the error/warning codes with which to
|
||||
extend the default ignore list.
|
||||
"""
|
||||
LOG.debug("Extending default ignore list with %r", error_codes)
|
||||
self.extended_default_ignore.extend(error_codes)
|
||||
|
||||
def extend_default_select(self, error_codes: Sequence[str]) -> None:
|
||||
"""Extend the default select list with the error codes provided.
|
||||
|
||||
:param error_codes:
|
||||
List of strings that are the error/warning codes with which
|
||||
to extend the default select list.
|
||||
"""
|
||||
LOG.debug("Extending default select list with %r", error_codes)
|
||||
self.extended_default_select.extend(error_codes)
|
||||
|
||||
def parse_args(
|
||||
self,
|
||||
args: Sequence[str] | None = None,
|
||||
values: argparse.Namespace | None = None,
|
||||
) -> argparse.Namespace:
|
||||
"""Proxy to calling the OptionParser's parse_args method."""
|
||||
if values:
|
||||
self.parser.set_defaults(**vars(values))
|
||||
return self.parser.parse_args(args)
|
||||
@@ -0,0 +1,70 @@
|
||||
"""Procedure for parsing args, config, loading plugins."""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
from typing import Sequence
|
||||
|
||||
import flake8
|
||||
from flake8.main import options
|
||||
from flake8.options import aggregator
|
||||
from flake8.options import config
|
||||
from flake8.options import manager
|
||||
from flake8.plugins import finder
|
||||
|
||||
|
||||
def parse_args(
|
||||
argv: Sequence[str],
|
||||
) -> tuple[finder.Plugins, argparse.Namespace]:
|
||||
"""Procedure for parsing args, config, loading plugins."""
|
||||
prelim_parser = options.stage1_arg_parser()
|
||||
|
||||
args0, rest = prelim_parser.parse_known_args(argv)
|
||||
# XXX (ericvw): Special case "forwarding" the output file option so
|
||||
# that it can be reparsed again for the BaseFormatter.filename.
|
||||
if args0.output_file:
|
||||
rest.extend(("--output-file", args0.output_file))
|
||||
|
||||
flake8.configure_logging(args0.verbose, args0.output_file)
|
||||
|
||||
cfg, cfg_dir = config.load_config(
|
||||
config=args0.config,
|
||||
extra=args0.append_config,
|
||||
isolated=args0.isolated,
|
||||
)
|
||||
|
||||
plugin_opts = finder.parse_plugin_options(
|
||||
cfg,
|
||||
cfg_dir,
|
||||
enable_extensions=args0.enable_extensions,
|
||||
require_plugins=args0.require_plugins,
|
||||
)
|
||||
raw_plugins = finder.find_plugins(cfg, plugin_opts)
|
||||
plugins = finder.load_plugins(raw_plugins, plugin_opts)
|
||||
|
||||
option_manager = manager.OptionManager(
|
||||
version=flake8.__version__,
|
||||
plugin_versions=plugins.versions_str(),
|
||||
parents=[prelim_parser],
|
||||
formatter_names=list(plugins.reporters),
|
||||
)
|
||||
options.register_default_options(option_manager)
|
||||
option_manager.register_plugins(plugins)
|
||||
|
||||
opts = aggregator.aggregate_options(option_manager, cfg, cfg_dir, rest)
|
||||
|
||||
for loaded in plugins.all_plugins():
|
||||
parse_options = getattr(loaded.obj, "parse_options", None)
|
||||
if parse_options is None:
|
||||
continue
|
||||
|
||||
# XXX: ideally we wouldn't have two forms of parse_options
|
||||
try:
|
||||
parse_options(
|
||||
option_manager,
|
||||
opts,
|
||||
opts.filenames,
|
||||
)
|
||||
except TypeError:
|
||||
parse_options(opts)
|
||||
|
||||
return plugins, opts
|
||||
Reference in New Issue
Block a user