diff --git a/.importlinter b/.importlinter new file mode 100644 index 000000000..011710125 --- /dev/null +++ b/.importlinter @@ -0,0 +1,84 @@ +[importlinter] +root_package = wemake_python_styleguide +include_external_packages = True + + +[importlinter:contract:layers] +name = Layered architecture of our linter +type = layers + +containers = + wemake_python_styleguide + +layers = + checker + transformations + presets + visitors + violations + logic + compat + options + constants + types + + +# TODO: provide independence contract for visitors +[importlinter:contract:violation-independence] +name = Independence contract for violations (all shall be free!) +type = independence + +modules = + wemake_python_styleguide.violations.naming + wemake_python_styleguide.violations.complexity + wemake_python_styleguide.violations.consistency + wemake_python_styleguide.violations.best_practices + wemake_python_styleguide.violations.refactoring + wemake_python_styleguide.violations.oop + + +[importlinter:contract:flake8-independence] +name = Independence contract for flake8 API (all shall be free!) +type = independence + +modules = + wemake_python_styleguide.checker + wemake_python_styleguide.formatter + + +[importlinter:contract:api-restrictions] +name = Forbids to import anything from dependencies +type = forbidden + +source_modules = + wemake_python_styleguide + +forbidden_modules = + # Important direct and indirect dependencies: + flake8 + pygments + isort + bandit + eradicate + pydocstyle + pycodestyle + mccabe + radon + +ignore_imports = + # These modules must import from flake8 to provide required API: + wemake_python_styleguide.checker -> flake8 + wemake_python_styleguide.formatter -> flake8 + wemake_python_styleguide.formatter -> pygments + wemake_python_styleguide.options.config -> flake8 + + +[importlinter:contract:tests-restrictions] +name = Explicit import restrictions for tests +type = forbidden + +source_modules = + wemake_python_styleguide + +forbidden_modules = + tests diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e20c547f6..9d4f74fbb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -75,13 +75,14 @@ These steps are mandatory during the CI. ## Architecture -We use [layer-lint](https://layer-linter.readthedocs.io/en/latest/usage.html) +We use [import-linter](https://import-linter.readthedocs.io) to enforce strict layered architecture. ```bash -layer-lint wemake_python_styleguide +lint-imports ``` +See `.importlinter` file for contracts definition. All contracts must be valid for each commit. This step is mandatory during the CI. @@ -141,7 +142,7 @@ Before submitting your code please do the following steps: 7. Run `pytest` again to make sure it is still working 8. Run `mypy` to ensure that types are correct 9. Run `flake8` to ensure that style is correct -10. Run `layer-lint` to ensure that architecture contracts are correct +10. Run `lint-imports` to ensure that architecture contracts are correct 11. Run `doc8` to ensure that docs are correct 12. Run `xenon` to ensure that code quality is `A` (good enough) diff --git a/Makefile b/Makefile index 74526b7f4..3205f2dbe 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ lint: flake8 . autopep8 -r . --diff --exclude=./tests/fixtures/** --exit-code xenon --max-absolute B --max-modules A --max-average A wemake_python_styleguide - layer-lint --quiet wemake_python_styleguide + lint-imports poetry run doc8 -q docs .PHONY: unit diff --git a/docs/pages/api/index.rst b/docs/pages/api/index.rst index a78909d75..101753523 100644 --- a/docs/pages/api/index.rst +++ b/docs/pages/api/index.rst @@ -68,8 +68,8 @@ to understand how all components are bound together. We use a `layered architecture `_ that follows this contract: -.. literalinclude :: ../../../layers.yml - :language: yaml +.. literalinclude :: ../../../.importlinter + :language: ini Contributing ------------ diff --git a/layers.yml b/layers.yml deleted file mode 100644 index fb6e29e86..000000000 --- a/layers.yml +++ /dev/null @@ -1,14 +0,0 @@ -Linting process: - containers: - - wemake_python_styleguide - layers: - - checker - - transformations - - presets - - visitors - - violations - - logic - - compat - - options - - constants - - types diff --git a/poetry.lock b/poetry.lock index 7f230b579..8660dc49f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -157,7 +157,7 @@ category = "main" description = "Docutils -- Python Documentation Utilities" name = "docutils" optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +python-versions = "*" version = "0.14" [[package]] @@ -479,6 +479,17 @@ ddt = ">=1.1.1" gitdb = ">=0.6.4" gitdb2 = ">=2.0.0" +[[package]] +category = "dev" +description = "Builds a graph of a Python project's internal and external dependencies." +name = "grimp" +optional = false +python-versions = "*" +version = "1.0b12" + +[package.dependencies] +networkx = ">=2.1,<3" + [[package]] category = "dev" description = "Internationalized Domain Names in Applications (IDNA)" @@ -495,6 +506,18 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" version = "1.1.0" +[[package]] +category = "dev" +description = "Enforces rules for the internal and external imports within your Python project." +name = "import-linter" +optional = false +python-versions = "*" +version = "1.0b4" + +[package.dependencies] +click = ">=6,<8" +grimp = "1.0b12" + [[package]] category = "dev" description = "Read metadata from Python packages" @@ -525,19 +548,6 @@ version = "2.10.1" [package.dependencies] MarkupSafe = ">=0.23" -[[package]] -category = "dev" -description = "Layer Linter checks that your project follows a custom-defined layered architecture." -name = "layer-linter" -optional = false -python-versions = "*" -version = "0.12.3" - -[package.dependencies] -PyYAML = ">=4.2b1,<5.0.0" -click = ">=6.7,<8" -networkx = ">=2.2,<3.0" - [[package]] category = "dev" description = "Markdown and reStructuredText in a single file." @@ -1079,7 +1089,7 @@ python-versions = ">=2.7" version = "0.5.2" [metadata] -content-hash = "66f1bc3833bba74038c7a5abd45136c5a19512d9778b139c77124bfa2bf7938b" +content-hash = "dd32036ae57c45a295c25dcc30a79c6eccafe4d98df2bfa3e3f60f73ceff2396" python-versions = "^3.6" [metadata.hashes] @@ -1099,7 +1109,7 @@ coverage = ["0c5fe441b9cfdab64719f24e9684502a59432df7570521563d7b1aff27ac755f", ddt = ["474546b4020ce8a2f9550ba8899c28aa2c284c7bbf175bddede98be949d1ca7c", "d13e6af8f36238e89d00f4ebccf2bda4f6d1878be560a6600689e42077e164e3"] decorator = ["86156361c50488b84a3f148056ea716ca587df2f0de1d34750d35c21312725de", "f069f3a01830ca754ba5258fde2278454a0b5b79e0d7f5c13b3b97e57d4acff6"] doc8 = ["2df89f9c1a5abfb98ab55d0175fed633cae0cf45025b8b1e0ee5ea772be28543", "d12f08aa77a4a65eb28752f4bc78f41f611f9412c4155e2b03f1f5d4a45efe04"] -docutils = ["554158db07870b514e8df93800e95ee8fbf2a2388eb453c7f69206532a8a6fa5", "82725b1051b92aaa42e240a4e5d6fafa2f6f5a2b5023b23a51c941dd7d863369"] +docutils = ["02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6", "51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274", "7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6"] dparse = ["00a5fdfa900629e5159bf3600d44905b333f4059a3366f28e0dbd13eeab17b19", "cef95156fa0adedaf042cd42f9990974bec76f25dfeca4dc01f381a243d5aa5b"] entrypoints = ["589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19", "c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451"] eradicate = ["4ffda82aae6fd49dfffa777a857cb758d77502a1f2e0f54c9ac5155a39d2d01a"] @@ -1128,12 +1138,13 @@ flake8-string-format = ["68ea72a1a5b75e7018cae44d14f32473c798cf73d75cbaed86c6a9a gitdb = ["a3ebbc27be035a2e874ed904df516e35f4a29a778a764385de09de9e0f139658"] gitdb2 = ["83361131a1836661a155172932a13c08bda2db3674e4caa32368aa6eb02f38c2", "e3a0141c5f2a3f635c7209d56c496ebe1ad35da82fe4d3ec4aaa36278d70648a"] gitpython = ["7428f1cc5e72d53e65c3259d5cebc22fb2b07f973c49d95b3c3d26c64890a3c3", "a0f744a4941eac5d99033eb0adcbec83bf443ee173fda4292d92a906aedce952"] +grimp = ["e8a5e004362b70d37a154e9daba5b1232ed58201e04630fe5d3e8839d72acefd"] idna = ["c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", "ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"] imagesize = ["3f349de3eb99145973fefb7dbe38554414e5c30abd0c8e4b970a7c9d09f3a1d8", "f3832918bc3c66617f92e35f5d70729187676313caa60c187eb0f28b8fe5e3b5"] +import-linter = ["1dadd9ca39414f3e76ea0ff9cced10b15bf294451a6ab0aba02aa87ec712d5b9"] importlib-metadata = ["6dfd58dfe281e8d240937776065dd3624ad5469c835248219bd16cf2e12dbeb7", "cb6ee23b46173539939964df59d3d72c3e0c1b5d54b84f1d8a7e912fe43612db"] isort = ["54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1", "6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd"] jinja2 = ["065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013", "14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b"] -layer-linter = ["1c937c0e3ee694b3abd701d7ee3e64d9c8ce5b442661bb1c119c9ba13908ec54", "c53d796270636c8363bd782e01f9852463c7d18574670a7586acee1e3ce55fe0"] m2r = ["bf90bad66cda1164b17e5ba4a037806d2443f2a4d5ddc9f6a5554a0322aaed99"] mando = ["4ce09faec7e5192ffc3c57830e26acba0fd6cd11e1ee81af0d4df0657463bd1c", "79feb19dc0f097daa64a1243db578e7674909b75f88ac2220f1c065c10a0d960"] markupsafe = ["00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", "09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", "09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", "1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", "24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", "29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", "43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", "46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", "500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", "535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", "62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", "6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", "717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", "79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", "7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", "88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", "8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", "98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", "9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", "9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", "ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", "b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", "b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", "b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", "ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", "c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", "cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", "e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"] diff --git a/pyproject.toml b/pyproject.toml index 91fa5bf7a..08f86eb3f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -93,6 +93,6 @@ m2r = "^0.2" added-value = "^0.14" tomlkit = "^0.5" safety = "^1.8" -layer-linter = "^0.12.3" autopep8 = "^1.4" xenon = "^0.5.5" +import-linter = {version = "1.0b4", allows-prereleases = true}