diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..b585fe04 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,18 @@ +# configuring pre-commit hooks for chasten. +# this ensures users do not commit problematic code +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: check-ast + - id: check-case-conflict + - id: check-merge-conflict + - id: forbid-submodules + - id: trailing-whitespace + + - repo: local + hooks: + - id: fix-imports + name: Fix Imports + entry: poetry run task fiximports + language: system diff --git a/chasten/checks.py b/chasten/checks.py index 6e1d2b54..c732f6c0 100644 --- a/chasten/checks.py +++ b/chasten/checks.py @@ -1,8 +1,13 @@ """Extract and analyze details about specific checks.""" -from typing import Dict, List, Tuple, Union - -from chasten import constants, enumerations, util +from typing import Dict +from typing import List +from typing import Tuple +from typing import Union + +from chasten import constants +from chasten import enumerations +from chasten import util def extract_min_max( diff --git a/chasten/configApp.py b/chasten/configApp.py index 2177f785..3b8d8d24 100644 --- a/chasten/configApp.py +++ b/chasten/configApp.py @@ -1,11 +1,16 @@ # Import necessary modules and components from the Textual library, # as well as other Python modules like os and validation tools. from pathlib import Path -from typing import ClassVar, List +from typing import ClassVar +from typing import List -from textual.app import App, ComposeResult +from textual.app import App +from textual.app import ComposeResult from textual.validation import Number -from textual.widgets import Button, Input, Pretty, Static +from textual.widgets import Button +from textual.widgets import Input +from textual.widgets import Pretty +from textual.widgets import Static from chasten import constants diff --git a/chasten/configuration.py b/chasten/configuration.py index d3c79033..d0130953 100644 --- a/chasten/configuration.py +++ b/chasten/configuration.py @@ -5,22 +5,25 @@ import logging.handlers import sys from pathlib import Path -from typing import Any, Dict, List, Tuple, Union +from typing import Any +from typing import Dict +from typing import List +from typing import Tuple +from typing import Union import platformdirs import requests import yaml from rich.logging import RichHandler from rich.traceback import install -from urllib3.util import Url, parse_url +from urllib3.util import Url +from urllib3.util import parse_url -from chasten import ( - constants, - filesystem, - output, - util, - validate, -) +from chasten import constants +from chasten import filesystem +from chasten import output +from chasten import util +from chasten import validate def configure_tracebacks() -> None: diff --git a/chasten/database.py b/chasten/database.py index fa28f7e5..2bab1673 100644 --- a/chasten/database.py +++ b/chasten/database.py @@ -6,7 +6,11 @@ from sqlite_utils import Database -from chasten import constants, enumerations, filesystem, output, util +from chasten import constants +from chasten import enumerations +from chasten import filesystem +from chasten import output +from chasten import util CHASTEN_SQL_SELECT_QUERY = """ SELECT diff --git a/chasten/filesystem.py b/chasten/filesystem.py index 28a3e8bb..33c2bfc5 100644 --- a/chasten/filesystem.py +++ b/chasten/filesystem.py @@ -5,12 +5,21 @@ import uuid from datetime import datetime from pathlib import Path -from typing import Any, Dict, List, NoReturn, Optional, Tuple, Union +from typing import Any +from typing import Dict +from typing import List +from typing import NoReturn +from typing import Optional +from typing import Tuple +from typing import Union import flatterer # type: ignore from rich.tree import Tree -from chasten import configuration, constants, database, results +from chasten import configuration +from chasten import constants +from chasten import database +from chasten import results CONFIGURATION_FILE_DEFAULT_CONTENTS = """ # chasten configuration diff --git a/chasten/main.py b/chasten/main.py index 309e462c..ec5dc3dd 100644 --- a/chasten/main.py +++ b/chasten/main.py @@ -4,27 +4,28 @@ import sys import time from pathlib import Path -from typing import Dict, List, Tuple, Union +from typing import Dict +from typing import List +from typing import Tuple +from typing import Union import typer from pyastgrep import search as pyastgrepsearch # type: ignore -from chasten import ( - checks, - configApp, - configuration, - constants, - createchecks, - database, - debug, - enumerations, - filesystem, - output, - process, - results, - server, - util, -) +from chasten import checks +from chasten import configApp +from chasten import configuration +from chasten import constants +from chasten import createchecks +from chasten import database +from chasten import debug +from chasten import enumerations +from chasten import filesystem +from chasten import output +from chasten import process +from chasten import results +from chasten import server +from chasten import util # create a Typer object to support the command-line interface cli = typer.Typer(no_args_is_help=True) diff --git a/chasten/output.py b/chasten/output.py index bfa8bb0d..c0bc78ac 100644 --- a/chasten/output.py +++ b/chasten/output.py @@ -3,14 +3,20 @@ import logging from copy import deepcopy from pathlib import Path -from typing import Any, Dict, List +from typing import Any +from typing import Dict +from typing import List from pyastgrep import search as pyastgrepsearch # type: ignore from rich.console import Console from rich.panel import Panel from rich.syntax import Syntax -from chasten import checks, configuration, constants, debug, results +from chasten import checks +from chasten import configuration +from chasten import constants +from chasten import debug +from chasten import results # declare a default logger logger: logging.Logger = logging.getLogger() diff --git a/chasten/process.py b/chasten/process.py index 5670b4e1..a701c059 100644 --- a/chasten/process.py +++ b/chasten/process.py @@ -1,12 +1,17 @@ """Analyze the abstract syntax tree, its XML-based representation, and/or the search results.""" import json -from typing import Any, Dict, List, Tuple, Union +from typing import Any +from typing import Dict +from typing import List +from typing import Tuple +from typing import Union from pyastgrep import search as pyastgrepsearch # type: ignore from thefuzz import fuzz # type: ignore -from chasten import constants, enumerations +from chasten import constants +from chasten import enumerations def include_or_exclude_checks( diff --git a/chasten/results.py b/chasten/results.py index d56b9101..7b9fd95e 100644 --- a/chasten/results.py +++ b/chasten/results.py @@ -3,7 +3,9 @@ import uuid from datetime import datetime from pathlib import Path -from typing import List, Optional, Union +from typing import List +from typing import Optional +from typing import Union from pyastgrep import search as pyastgrepsearch # type: ignore from pydantic import BaseModel diff --git a/chasten/server.py b/chasten/server.py index acf75116..e6e813d5 100644 --- a/chasten/server.py +++ b/chasten/server.py @@ -4,7 +4,8 @@ import logging.handlers import socketserver -from chasten import constants, output +from chasten import constants +from chasten import output LOG_FILE = constants.server.Log_File HOST = constants.server.Localhost diff --git a/chasten/validate.py b/chasten/validate.py index 1b25e0a9..bca221c8 100644 --- a/chasten/validate.py +++ b/chasten/validate.py @@ -1,11 +1,16 @@ """Validate various aspects of configurations and command-line arguments.""" -from typing import Any, Dict, List, Tuple +from typing import Any +from typing import Dict +from typing import List +from typing import Tuple import jsonschema from jsonschema.exceptions import ValidationError -from chasten import constants, output, util +from chasten import constants +from chasten import output +from chasten import util # intuitive description: # a configuration file links to one or more checks files diff --git a/poetry.lock b/poetry.lock index 2b35cccd..21925411 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. [[package]] name = "aiofiles" @@ -275,6 +275,7 @@ files = [ {file = "black-23.11.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5133f5507007ba08d8b7b263c7aa0f931af5ba88a29beacc4b2dc23fcefe9c06"}, {file = "black-23.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:421f3e44aa67138ab1b9bfbc22ee3780b22fa5b291e4db8ab7eee95200726b07"}, {file = "black-23.11.0-py3-none-any.whl", hash = "sha256:54caaa703227c6e0c87b76326d0862184729a69b73d3b7305b6288e1d830067e"}, + {file = "black-23.11.0.tar.gz", hash = "sha256:4c68855825ff432d197229846f971bc4d6666ce90492e5b02013bcaca4d9ab05"}, ] [package.dependencies] @@ -376,6 +377,17 @@ files = [ [package.dependencies] pycparser = "*" +[[package]] +name = "cfgv" +version = "3.4.0" +description = "Validate configuration and produce human readable error messages." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, + {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, +] + [[package]] name = "charset-normalizer" version = "3.3.2" @@ -842,6 +854,17 @@ sqlite-regex = "*" [package.extras] test = ["pytest"] +[[package]] +name = "distlib" +version = "0.3.7" +description = "Distribution utilities" +optional = false +python-versions = "*" +files = [ + {file = "distlib-0.3.7-py2.py3-none-any.whl", hash = "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057"}, + {file = "distlib-0.3.7.tar.gz", hash = "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8"}, +] + [[package]] name = "elementpath" version = "4.1.5" @@ -870,6 +893,22 @@ files = [ [package.extras] testing = ["hatch", "pre-commit", "pytest", "tox"] +[[package]] +name = "filelock" +version = "3.13.1" +description = "A platform independent file lock." +optional = false +python-versions = ">=3.8" +files = [ + {file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"}, + {file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"}, +] + +[package.extras] +docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.24)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +typing = ["typing-extensions (>=4.8)"] + [[package]] name = "flask" version = "3.0.0" @@ -1167,6 +1206,20 @@ files = [ hypothesis = ">=6.31.6" jsonschema = ">=4.0.0" +[[package]] +name = "identify" +version = "2.5.32" +description = "File identification library for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "identify-2.5.32-py2.py3-none-any.whl", hash = "sha256:0b7656ef6cba81664b783352c73f8c24b39cf82f926f78f4550eda928e5e0545"}, + {file = "identify-2.5.32.tar.gz", hash = "sha256:5d9979348ec1a21c768ae07e0a652924538e8bce67313a73cb0f681cf08ba407"}, +] + +[package.extras] +license = ["ukkonen"] + [[package]] name = "idna" version = "3.4" @@ -1987,6 +2040,20 @@ files = [ {file = "nest_asyncio-1.5.8.tar.gz", hash = "sha256:25aa2ca0d2a5b5531956b9e273b45cf664cae2b145101d73b86b199978d48fdb"}, ] +[[package]] +name = "nodeenv" +version = "1.8.0" +description = "Node.js virtual environment builder" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" +files = [ + {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, + {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, +] + +[package.dependencies] +setuptools = "*" + [[package]] name = "numpy" version = "1.26.2" @@ -2293,6 +2360,24 @@ files = [ {file = "pprintpp-0.4.0.tar.gz", hash = "sha256:ea826108e2c7f49dc6d66c752973c3fc9749142a798d6b254e1e301cfdbc6403"}, ] +[[package]] +name = "pre-commit" +version = "3.5.0" +description = "A framework for managing and maintaining multi-language pre-commit hooks." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pre_commit-3.5.0-py2.py3-none-any.whl", hash = "sha256:841dc9aef25daba9a0238cd27984041fa0467b4199fc4852e27950664919f660"}, + {file = "pre_commit-3.5.0.tar.gz", hash = "sha256:5804465c675b659b0862f07907f96295d490822a450c4c40e747d0b1c6ebcb32"}, +] + +[package.dependencies] +cfgv = ">=2.0.0" +identify = ">=1.0.0" +nodeenv = ">=0.11.1" +pyyaml = ">=5.1" +virtualenv = ">=20.10.0" + [[package]] name = "psutil" version = "5.9.6" @@ -3442,6 +3527,26 @@ h11 = ">=0.8" [package.extras] standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] +[[package]] +name = "virtualenv" +version = "20.24.7" +description = "Virtual Python Environment builder" +optional = false +python-versions = ">=3.7" +files = [ + {file = "virtualenv-20.24.7-py3-none-any.whl", hash = "sha256:a18b3fd0314ca59a2e9f4b556819ed07183b3e9a3702ecfe213f593d44f7b3fd"}, + {file = "virtualenv-20.24.7.tar.gz", hash = "sha256:69050ffb42419c91f6c1284a7b24e0475d793447e35929b488bf6a0aade39353"}, +] + +[package.dependencies] +distlib = ">=0.3.7,<1" +filelock = ">=3.12.2,<4" +platformdirs = ">=3.9.1,<5" + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] + [[package]] name = "werkzeug" version = "3.0.1" @@ -3575,4 +3680,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "919229c283aae8adf17519b2722864f93f07b41cee22c9cced339ef555027dd0" +content-hash = "25211477e5ff090ff973ffb08bccd8400a813fb4bf1141756214a9e544313170" diff --git a/pyproject.toml b/pyproject.toml index bb7654a6..7ab2d74a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,6 +53,7 @@ types-pyyaml = "^6.0.12.10" types-jsonschema = "^4.17.0.9" types-requests = "^2.31.0.10" hypothesis-jsonschema = "^0.22.1" +pre-commit = "^3.5.0" pytest-clarity = "^1.0.1" pytest-randomly = "^3.13.0" pytest-pretty = "^1.2.0" @@ -119,6 +120,7 @@ test-api = { cmd = "{openai-test}", help = "Run openai powered test cases", use_ not-openai-test = { cmd = "{not-openai-test}", help = "Run openai powered test cases", use_vars = true } test-coverage = { cmd = "{coverage-test-command}", help = "Run coverage monitoring for the test suite", use_vars = true } test-coverage-silent = { cmd = "{coverage-test-command-silent}", help = "Run coverage monitoring for tests without output", use_vars = true } +pre-commit-install = { cmd = "pre-commit install", help = "Install or update pre-commit hooks" } [build-system] requires = ["poetry-core"] diff --git a/tests/test_checks.py b/tests/test_checks.py index 9c1dd093..893b130d 100644 --- a/tests/test_checks.py +++ b/tests/test_checks.py @@ -2,14 +2,14 @@ import hypothesis.strategies as st import pytest -from hypothesis import HealthCheck, given, settings +from hypothesis import HealthCheck +from hypothesis import given +from hypothesis import settings from hypothesis_jsonschema import from_schema -from chasten.checks import ( - check_match_count, - extract_min_max, - is_in_closed_interval, -) +from chasten.checks import check_match_count +from chasten.checks import extract_min_max +from chasten.checks import is_in_closed_interval from chasten.validate import JSON_SCHEMA_CHECKS JSON_SCHEMA_COUNT = { diff --git a/tests/test_configApp.py b/tests/test_configApp.py index 9850774f..854219b9 100644 --- a/tests/test_configApp.py +++ b/tests/test_configApp.py @@ -1,10 +1,13 @@ import pathlib import pytest -from hypothesis import HealthCheck, given, settings +from hypothesis import HealthCheck +from hypothesis import given +from hypothesis import settings from hypothesis import strategies as st -from chasten import configApp, constants +from chasten import configApp +from chasten import constants # Define an alphabet of characters for generating random test data ALPHABET = "0123456789!@#$%^&*()_+-=[]|:;'<>.?/~`AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz" diff --git a/tests/test_configuration.py b/tests/test_configuration.py index 739572a4..184dd0fe 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -3,7 +3,8 @@ import logging import pytest -from hypothesis import given, strategies +from hypothesis import given +from hypothesis import strategies from chasten import configuration diff --git a/tests/test_constants.py b/tests/test_constants.py index b914e588..5c119dd7 100644 --- a/tests/test_constants.py +++ b/tests/test_constants.py @@ -4,7 +4,8 @@ from pathlib import Path import pytest -from hypothesis import given, strategies +from hypothesis import given +from hypothesis import strategies from chasten import constants diff --git a/tests/test_createchecks.py b/tests/test_createchecks.py index 9a924fca..27219405 100644 --- a/tests/test_createchecks.py +++ b/tests/test_createchecks.py @@ -3,7 +3,8 @@ import pytest -from chasten.createchecks import generate_yaml_config, is_valid_api_key +from chasten.createchecks import generate_yaml_config +from chasten.createchecks import is_valid_api_key def get_valid_api_key(): diff --git a/tests/test_debug.py b/tests/test_debug.py index 0303ea8d..e486f86d 100644 --- a/tests/test_debug.py +++ b/tests/test_debug.py @@ -2,7 +2,8 @@ import pytest -from chasten.debug import DebugDestination, DebugLevel +from chasten.debug import DebugDestination +from chasten.debug import DebugLevel def test_debug_level_values(): diff --git a/tests/test_filesystem.py b/tests/test_filesystem.py index ac3289f3..17c06438 100644 --- a/tests/test_filesystem.py +++ b/tests/test_filesystem.py @@ -5,10 +5,12 @@ from unittest.mock import patch import pytest -from hypothesis import given, strategies +from hypothesis import given +from hypothesis import strategies from rich.tree import Tree -from chasten import constants, filesystem +from chasten import constants +from chasten import filesystem def test_valid_directory() -> None: diff --git a/tests/test_main.py b/tests/test_main.py index 65369ed5..8f43a1d0 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -5,7 +5,10 @@ from unittest.mock import patch import pytest -from hypothesis import HealthCheck, given, settings, strategies +from hypothesis import HealthCheck +from hypothesis import given +from hypothesis import settings +from hypothesis import strategies from typer.testing import CliRunner from chasten import main diff --git a/tests/test_util.py b/tests/test_util.py index 7ed69a7c..c411d38d 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -3,10 +3,12 @@ import shutil import pytest -from hypothesis import given, provisional +from hypothesis import given +from hypothesis import provisional from hypothesis import strategies as st -from chasten import constants, util +from chasten import constants +from chasten import util def test_human_readable_boolean() -> None: diff --git a/tests/test_validate.py b/tests/test_validate.py index 87845f23..6625a401 100644 --- a/tests/test_validate.py +++ b/tests/test_validate.py @@ -1,10 +1,14 @@ """Pytest test suite for the validate module.""" import pytest -from hypothesis import HealthCheck, given, settings, strategies +from hypothesis import HealthCheck +from hypothesis import given +from hypothesis import settings +from hypothesis import strategies from hypothesis_jsonschema import from_schema -from chasten.validate import JSON_SCHEMA_CONFIG, validate_configuration +from chasten.validate import JSON_SCHEMA_CONFIG +from chasten.validate import validate_configuration def test_validate_config_valid_realistic():