Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check if lines exist on a text file #182

Merged
merged 7 commits into from
Jul 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ repos:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/asottile/pyupgrade
rev: v2.6.2
rev: v2.7.0
hooks:
- id: pyupgrade
- repo: https://github.com/python/black
Expand All @@ -27,7 +27,7 @@ repos:
hooks:
- id: seed-isort-config
- repo: https://github.com/pre-commit/mirrors-isort
rev: v4.3.21
rev: v5.0.9
hooks:
- id: isort
- repo: https://github.com/pre-commit/pygrep-hooks
Expand Down
6 changes: 4 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ always-run:
.PHONY: always-run

pre-commit .cache/make/long-pre-commit: .pre-commit-config.yaml .pre-commit-hooks.yaml # Update and install pre-commit hooks
# TODO: isort 5.0.0 is apparently broken, so we can't autoupdate for now
# pre-commit autoupdate
@# Uncomment the lines below to autoupdate all repos except a few filtered out with egrep
# yq -r '.repos[].repo' .pre-commit-config.yaml | egrep -v -e '^local' -e mirrors-isort | \
# sed -E -e 's/http/--repo http/g' | xargs pre-commit autoupdate
pre-commit autoupdate
pre-commit install --install-hooks
pre-commit install --hook-type commit-msg
pre-commit gc
Expand Down
4 changes: 2 additions & 2 deletions docs/defaults.rst
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ Content of `styles/isort.toml <https://raw.githubusercontent.com/andreoliwa/nitp
hooks:
- id: seed-isort-config
- repo: https://github.com/pre-commit/mirrors-isort
rev: v4.3.21
rev: v5.0.9
hooks:
- id: isort
"""
Expand Down Expand Up @@ -266,7 +266,7 @@ Content of `styles/pre-commit/general.toml <https://raw.githubusercontent.com/an
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/asottile/pyupgrade
rev: v2.6.2
rev: v2.7.0
hooks:
- id: pyupgrade
"""
Expand Down
46 changes: 17 additions & 29 deletions docs/generate_rst.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,8 @@
from slugify import slugify
from sortedcontainers import SortedDict

from nitpick.app import NitpickApp
from nitpick.constants import RAW_GITHUB_CONTENT_BASE_URL
from nitpick.generic import get_subclasses
from nitpick.plugins.base import BaseFile
from nitpick.plugins.json import JSONFile
from nitpick.plugins.pre_commit import PreCommitFile
from nitpick.plugins.pyproject_toml import PyProjectTomlFile
from nitpick.plugins.setup_cfg import SetupCfgFile

style_mapping = SortedDict(
{
Expand All @@ -47,7 +42,7 @@
"python37.toml": "Python 3.7",
}
)
file_classes = [PyProjectTomlFile, SetupCfgFile, PreCommitFile, JSONFile]
app = NitpickApp.create_app()

divider = ".. auto-generated-from-here"
docs_dir = Path(__file__).parent.absolute() # type: Path
Expand Down Expand Up @@ -122,9 +117,9 @@ def generate_defaults_rst():
sys.exit(1)


def generate_config_files_rst():
"""Generate config_files.rst with the docstrings from BaseFile classes."""
rst_file = docs_dir / "config_files.rst" # type: Path
def generate_plugins_rst():
"""Generate plugins.rst with the docstrings from :py:class:`nitpick.plugins.base.NitpickPlugin` classes."""
rst_file = docs_dir / "plugins.rst" # type: Path

template = """
.. _{link}:
Expand All @@ -136,40 +131,33 @@ def generate_config_files_rst():
"""
clean_template = dedent(template).strip()
blocks = []
for file_class in file_classes:
header = file_class.file_name

# Sort order: classes with fixed file names first, then alphabetically by class name
for plugin_class in sorted(
app.plugin_manager.hook.plugin_class(), key=lambda c: "0" if c.file_name else "1" + c.__name__
):
header = plugin_class.file_name
if not header:
# module_name = file_class.__module__
module = import_module(file_class.__module__)
module = import_module(plugin_class.__module__)
header = module.__doc__.strip(" .")

stripped_lines = [line.strip() for line in file_class.__doc__.split("\n")]
# Padding with any char except space (it doesn't work)
indented_doc = "xxxx" + plugin_class.__doc__
stripped_lines = [line[4:] for line in indented_doc.split("\n")]

blocks.append("")
blocks.append(
clean_template.format(
link=slugify(file_class.__name__),
link=slugify(plugin_class.__name__),
header=header,
dashes="-" * len(header),
description="\n".join(stripped_lines).strip(),
)
)
write_rst(rst_file, blocks)

existing = set(get_subclasses(BaseFile))
documented = set(file_classes)
something_missing = existing - documented
for missing_class in something_missing:
click.secho(
"ERROR: Add missing base file {} to the 'file_classes' var in '{}'.".format(
missing_class.__name__, __file__
),
fg="red",
)
if something_missing:
sys.exit(1)


if __name__ == "__main__":
generate_defaults_rst()
generate_config_files_rst()
generate_plugins_rst()
2 changes: 1 addition & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Useful if you maintain multiple projects and want to use the same configs in all
auto_detection
tool_nitpick_section
nitpick_section
config_files
plugins
defaults
troubleshooting
contributing
Expand Down
2 changes: 1 addition & 1 deletion docs/nitpick_section.rst
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,5 @@ If a key/value pair appears in more than one sub-style, it will be overridden; t
[nitpick.JSONFile]
------------------

Configure the list of filenames that should be checked by the :py:class:`nitpick.plugins.json.JSONFile` class.
Configure the list of filenames that should be checked by the :py:class:`nitpick.plugins.json.JSONPlugin` class.
See :ref:`the default package.json style <default-package-json>` for an example of usage.
49 changes: 33 additions & 16 deletions docs/config_files.rst → docs/plugins.rst
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
.. include:: targets.rst
.. _config_files:
.. _plugins:

Configuration files
===================
Plugins
=======

Below are the currently supported configuration files.
Below are the currently included plugins.

.. auto-generated-from-here

.. _pyprojecttomlfile:
.. _setupcfgplugin:

setup.cfg
---------

Checker for the `setup.cfg <https://docs.python.org/3/distutils/configfile.html>`_ config file.

Example: :ref:`flake8 configuration <default-flake8>`.

.. _pyprojecttomlplugin:

pyproject.toml
--------------
Expand All @@ -20,16 +29,7 @@ See also `PEP 518 <https://www.python.org/dev/peps/pep-0518/>`_.
Example: :ref:`the Python 3.7 default <default-python-3-7>`.
There are many other examples in :ref:`defaults`.

.. _setupcfgfile:

setup.cfg
---------

Checker for the `setup.cfg <https://docs.python.org/3/distutils/configfile.html>`_ config file.

Example: :ref:`flake8 configuration <default-flake8>`.

.. _precommitfile:
.. _precommitplugin:

.pre-commit-config.yaml
-----------------------
Expand All @@ -38,7 +38,7 @@ Checker for the `.pre-commit-config.yaml <https://pre-commit.com/#pre-commit-con

Example: :ref:`the default pre-commit hooks <default-pre-commit-hooks>`.

.. _jsonfile:
.. _jsonplugin:

JSON files
----------
Expand All @@ -52,3 +52,20 @@ Example: :ref:`the default config for package.json <default-package-json>`.

If a JSON file is configured on ``[nitpick.JSONFile] file_names``, then a configuration for it should exist.
Otherwise, a style validation error will be raised.

.. _textplugin:

Text files
----------

Checker for text files.

To check if ``some.txt`` file contains the lines ``abc`` and ``def`` (in any order):

.. code-block:: toml

[["some.txt".contains]]
line = "abc"

[["some.txt".contains]]
line = "def"
1 change: 1 addition & 0 deletions docs/source/nitpick.plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ Submodules
nitpick.plugins.pre_commit
nitpick.plugins.pyproject_toml
nitpick.plugins.setup_cfg
nitpick.plugins.text
7 changes: 7 additions & 0 deletions docs/source/nitpick.plugins.text.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
nitpick.plugins.text module
===========================

.. automodule:: nitpick.plugins.text
:members:
:undoc-members:
:show-inheritance:
18 changes: 9 additions & 9 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ classifiers = [
NIP = "nitpick.flake8:NitpickExtension"

[tool.poetry.plugins.nitpick]
text = "nitpick.plugins.text"
json = "nitpick.plugins.json"
pre_commit = "nitpick.plugins.pre_commit"
setup_cfg = "nitpick.plugins.setup_cfg"
Expand Down
10 changes: 5 additions & 5 deletions src/nitpick/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def create_app(cls, offline=False) -> "NitpickApp":
"""Create a single application."""
# pylint: disable=import-outside-toplevel
from nitpick.config import Config # pylint: disable=redefined-outer-name
from nitpick.plugins.base import BaseFile
from nitpick.plugins.base import NitpickPlugin

app = cls()
cls._current_app = app
Expand All @@ -63,7 +63,7 @@ def create_app(cls, offline=False) -> "NitpickApp":
app.main_python_file = app.find_main_python_file()
app.config = Config()
app.plugin_manager = app.load_plugins()
BaseFile.load_fixed_dynamic_classes()
NitpickPlugin.load_fixed_dynamic_classes()
except (NoRootDir, NoPythonFile) as err:
app.init_errors.append(err)

Expand All @@ -89,8 +89,8 @@ def find_root_dir() -> Path:
Start from the current working dir.
"""
# pylint: disable=import-outside-toplevel
from nitpick.plugins.pyproject_toml import PyProjectTomlFile
from nitpick.plugins.setup_cfg import SetupCfgFile
from nitpick.plugins.pyproject_toml import PyProjectTomlPlugin
from nitpick.plugins.setup_cfg import SetupCfgPlugin

root_dirs = set() # type: Set[Path]
seen = set() # type: Set[Path]
Expand All @@ -101,7 +101,7 @@ def find_root_dir() -> Path:
starting_dir = Path(starting_file).parent.absolute()
while True:
project_files = climb_directory_tree(
starting_dir, ROOT_FILES + (PyProjectTomlFile.file_name, SetupCfgFile.file_name)
starting_dir, ROOT_FILES + (PyProjectTomlPlugin.file_name, SetupCfgPlugin.file_name)
)
if project_files and project_files & seen:
break
Expand Down
13 changes: 7 additions & 6 deletions src/nitpick/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@
TOOL_NITPICK,
TOOL_NITPICK_JMEX,
)
from nitpick.formats import TomlFormat
from nitpick.formats import TOMLFormat
from nitpick.generic import search_dict, version_to_tuple
from nitpick.mixin import NitpickMixin
from nitpick.plugins.pyproject_toml import PyProjectTomlFile
from nitpick.plugins.pyproject_toml import PyProjectTomlPlugin
from nitpick.schemas import ToolNitpickSectionSchema, flatten_marshmallow_errors
from nitpick.style import Style
from nitpick.typedefs import YieldFlake8Error

if TYPE_CHECKING:
from pathlib import Path

from nitpick.typedefs import JsonDict, StrOrList

LOGGER = logging.getLogger(__name__)
Expand All @@ -32,22 +33,22 @@ class Config(NitpickMixin): # pylint: disable=too-many-instance-attributes

def __init__(self) -> None:

self.pyproject_toml = None # type: Optional[TomlFormat]
self.pyproject_toml = None # type: Optional[TOMLFormat]
self.tool_nitpick_dict = {} # type: JsonDict
self.style_dict = {} # type: JsonDict
self.nitpick_section = {} # type: JsonDict
self.nitpick_files_section = {} # type: JsonDict

def validate_pyproject_tool_nitpick(self) -> bool:
"""Validate the ``pyroject.toml``'s ``[tool.nitpick]`` section against a Marshmallow schema."""
pyproject_path = NitpickApp.current().root_dir / PyProjectTomlFile.file_name # type: Path
pyproject_path = NitpickApp.current().root_dir / PyProjectTomlPlugin.file_name # type: Path
if pyproject_path.exists():
self.pyproject_toml = TomlFormat(path=pyproject_path)
self.pyproject_toml = TOMLFormat(path=pyproject_path)
self.tool_nitpick_dict = search_dict(TOOL_NITPICK_JMEX, self.pyproject_toml.as_data, {})
pyproject_errors = ToolNitpickSectionSchema().validate(self.tool_nitpick_dict)
if pyproject_errors:
NitpickApp.current().add_style_error(
PyProjectTomlFile.file_name,
PyProjectTomlPlugin.file_name,
"Invalid data in [{}]:".format(TOOL_NITPICK),
flatten_marshmallow_errors(pyproject_errors),
)
Expand Down