Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def __init__(self, pytest_request: FixtureRequest, **kwargs) -> None:
"""Create the root dir and make it the current dir (needed by NitpickChecker)."""
subdir = "/".join(pytest_request.module.__name__.split(".")[1:])
caller_function_name = pytest_request.node.name
self.root_dir = TEMP_ROOT_PATH / subdir / caller_function_name # type: Path
# To make debugging of mock projects easy, each test should not reuse another test directory.
self.root_dir.mkdir(parents=True)
self.cache_dir = self.root_dir / CACHE_DIR_NAME / PROJECT_NAME
self.files_to_lint = [] # type: List[Path]
if kwargs.get("setup_py", True):
self.save_file("setup.py", "x = 1")
return []
LOGGER.debug("Nitpicking file: %s", self.filename)
yield from itertools.chain(app.config.merge_styles(), self.check_files(True), self.check_files(False))
has_errors = False
for err in app.style_errors:
has_errors = True
yield NitpickApp.as_flake8_warning(err)
if has_errors:
return []
# Get all root keys from the style TOML.
for path, config_dict in app.config.style_dict.items():
# All except "nitpick" are file names.
if path == PROJECT_NAME:
continue
# For each file name, find the plugin that can handle the file.
tags = identify.tags_from_filename(path)
for base_file in app.plugin_manager.hook.handle_config_file( # pylint: disable=no-member
config=config_dict, file_name=path, tags=tags
):
yield from base_file.check_exists()
return []
def clear_cache_dir(self) -> Path:
"""Clear the cache directory (on the project root or on the current directory)."""
cache_root = self.root_dir / CACHE_DIR_NAME # type: Path
cache_dir = cache_root / PROJECT_NAME
rmtree(str(cache_dir), ignore_errors=True)
return cache_dir
The hook specifications and the plugin classes are still experimental and considered as an internal API.
They might change at any time; use at your own risk.
"""
from typing import TYPE_CHECKING, Optional, Set, Type
import pluggy
from nitpick.constants import PROJECT_NAME
from nitpick.typedefs import JsonDict
if TYPE_CHECKING:
from nitpick.plugins.base import NitpickPlugin
hookspec = pluggy.HookspecMarker(PROJECT_NAME)
hookimpl = pluggy.HookimplMarker(PROJECT_NAME)
@hookspec
def plugin_class() -> Type["NitpickPlugin"]:
"""You should return your plugin class here."""
@hookspec
def handle_config_file( # pylint: disable=unused-argument
config: JsonDict, file_name: str, tags: Set[str]
) -> Optional["NitpickPlugin"]:
"""You should return a valid :py:class:`nitpick.plugins.base.NitpickPlugin` instance or ``None``.
The hook specifications and the plugin classes are still experimental and considered as an internal API.
They might change at any time; use at your own risk.
"""
from typing import TYPE_CHECKING, Optional, Set, Type
import pluggy
from nitpick.constants import PROJECT_NAME
from nitpick.typedefs import JsonDict
if TYPE_CHECKING:
from nitpick.plugins.base import NitpickPlugin
hookspec = pluggy.HookspecMarker(PROJECT_NAME)
hookimpl = pluggy.HookimplMarker(PROJECT_NAME)
@hookspec
def plugin_class() -> Type["NitpickPlugin"]:
"""You should return your plugin class here."""
@hookspec
def handle_config_file( # pylint: disable=unused-argument
config: JsonDict, file_name: str, tags: Set[str]
) -> Optional["NitpickPlugin"]:
"""You should return a valid :py:class:`nitpick.plugins.base.NitpickPlugin` instance or ``None``.
def load_plugins() -> PluginManager:
"""Load all defined plugins."""
plugin_manager = pluggy.PluginManager(PROJECT_NAME)
plugin_manager.add_hookspecs(plugins)
plugin_manager.load_setuptools_entrypoints(PROJECT_NAME)
return plugin_manager
configured_styles = self.tool_nitpick_dict.get("style", "") # type: StrOrList
style = Style()
style.find_initial_styles(configured_styles)
self.style_dict = style.merge_toml_dict()
if not NitpickApp.current().style_errors:
# Don't show duplicated errors: if there are style errors already, don't validate the merged style.
style.validate_style(MERGED_STYLE_TOML, self.style_dict)
from nitpick.flake8 import NitpickExtension # pylint: disable=import-outside-toplevel
minimum_version = search_dict(NITPICK_MINIMUM_VERSION_JMEX, self.style_dict, None)
if minimum_version and version_to_tuple(NitpickExtension.version) < version_to_tuple(minimum_version):
yield self.flake8_error(
3,
"The style file you're using requires {}>={}".format(PROJECT_NAME, minimum_version)
+ " (you have {}). Please upgrade".format(NitpickExtension.version),
)
self.nitpick_section = self.style_dict.get("nitpick", {})
self.nitpick_files_section = self.nitpick_section.get("files", {})
def validate_style(self, style_file_name: str, original_data: JsonDict):
"""Validate a style file (TOML) against a Marshmallow schema."""
self.rebuild_dynamic_schema(original_data)
style_errors = self._dynamic_schema_class().validate(original_data)
if style_errors:
has_nitpick_jsonfile_section = style_errors.get(PROJECT_NAME, {}).pop("JSONFile", None)
if has_nitpick_jsonfile_section:
warnings.warn(
"The [nitpick.JSONFile] section is not needed anymore; just declare your JSON files directly",
DeprecationWarning,
)
if not style_errors[PROJECT_NAME]:
style_errors.pop(PROJECT_NAME)
if style_errors:
NitpickApp.current().add_style_error(
style_file_name, "Invalid config:", flatten_marshmallow_errors(style_errors)
)
from nitpick import __version__
from nitpick.app import NitpickApp
from nitpick.constants import PROJECT_NAME
from nitpick.mixin import NitpickMixin
from nitpick.typedefs import YieldFlake8Error
LOGGER = logging.getLogger(__name__)
@attr.s(hash=False)
class NitpickExtension(NitpickMixin):
"""Main class for the flake8 extension."""
# Plugin config
name = PROJECT_NAME
version = __version__
# NitpickMixin
error_base_number = 100
# Plugin arguments passed by Flake8
tree = attr.ib(default=None)
filename = attr.ib(default="(none)")
def run(self) -> YieldFlake8Error:
"""Run the check plugin."""
has_errors = False
app = NitpickApp.current()
for err in app.init_errors:
has_errors = True
yield NitpickApp.as_flake8_warning(err)
def validate_style(self, style_file_name: str, original_data: JsonDict):
"""Validate a style file (TOML) against a Marshmallow schema."""
self.rebuild_dynamic_schema(original_data)
style_errors = self._dynamic_schema_class().validate(original_data)
if style_errors:
has_nitpick_jsonfile_section = style_errors.get(PROJECT_NAME, {}).pop("JSONFile", None)
if has_nitpick_jsonfile_section:
warnings.warn(
"The [nitpick.JSONFile] section is not needed anymore; just declare your JSON files directly",
DeprecationWarning,
)
if not style_errors[PROJECT_NAME]:
style_errors.pop(PROJECT_NAME)
if style_errors:
NitpickApp.current().add_style_error(
style_file_name, "Invalid config:", flatten_marshmallow_errors(style_errors)
)