{"id":304057,"date":"2020-05-22T09:00:39","date_gmt":"2020-05-22T09:00:39","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=304057"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=304057","title":{"rendered":"\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f .pre-commit hook \u0432 Django \u043f\u0440\u043e\u0435\u043a\u0442"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/503270\/\">\u0414\u043e\u0431\u0440\u043e\u0433\u043e \u0434\u043d\u044f!<\/p>\n<p>  \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0421\u043e\u0431\u043e\u043b\u0435\u0432 \u0410\u043d\u0434\u0440\u0435\u0439 \u0438 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u044f \u0432\u0430\u043c \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043a\u0430\u043a \u043c\u044b \u043f\u0440\u0438\u0433\u043e\u0442\u043e\u0432\u0438\u043b\u0438 .pre-commit hook \u043d\u0430 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435.<\/p>\n<h3>\u0412\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0435<\/h3>\n<p>  \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0430\u0440\u0443 \u0441\u043b\u043e\u0432, \u043e \u0442\u043e\u043c \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0432 \u0446\u0435\u043b\u043e\u043c \u0445\u0443\u043a\u0438 (hooks) \u0438 \u0434\u043b\u044f \u0447\u0435\u0433\u043e \u043e\u043d\u0438 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u0443\u0436\u043d\u044b. Git \u00ab\u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438\u00bb \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u043c\u0435\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0432\u0430\u0448\u0438 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u043f\u0440\u0438 \u043d\u0430\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0438 \u043a\u0430\u043a\u043e\u0433\u043e \u043b\u0438\u0431\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044f (\u043a \u043f\u0440\u0438\u043c\u0435\u0440\u0443 \u043f\u0443\u0448 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0438 \u0442.\u043f.)<\/p>\n<p>  .pre-commit \u044d\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u0430\u044f \u043d\u0430\u0434\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043d\u0430\u0434 \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u043c git pre-commit hook, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u0432 .pre-commit-config.yaml \u043f\u0435\u0440\u0435\u0434 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435\u043c \u043a\u043e\u043c\u043c\u0438\u0442\u0430. \u0412 \u0442\u0435\u043e\u0440\u0438\u0438 \u0437\u0432\u0443\u0447\u0438\u0442 \u043f\u0440\u043e\u0441\u0442\u043e, \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435.<\/p>\n<p>  <a name=\"habracut\"><\/a>  <\/p>\n<h3>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430<\/h3>\n<p>  \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438  <\/p>\n<pre><code class=\"python\">pre-commit # \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u0430\u043a\u0435\u0442 https:\/\/pre-commit.com\/  autoflake # \u0434\u043b\u044f \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u043d\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0438\u043c\u043f\u043e\u0440\u0442\u043e\u0432 (\u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435) black # \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u0443\u0435\u043c \u043a\u043e\u0434 pyupgrade # \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u043c \u0435\u0433\u043e \u043a \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 reorder-python-imports # \u0434\u0435\u043b\u0430\u0435\u043c \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u044b yesqa # \u0443\u0434\u0430\u043b\u044f\u0435\u043c \u043d\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 noqa \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438 (\u0434\u043b\u044f \u043b\u0438\u043d\u0442\u0435\u0440\u043e\u0432)  # \u043b\u0438\u043d\u0442\u0435\u0440\u044b flake8 flake8-annotations flake8-annotations-coverage flake8-bandit flake8-broken-line flake8-bugbear flake8-builtins flake8-commas flake8-comprehensions flake8-debugger flake8-eradicate flake8-executable flake8-fixme flake8-future-import flake8-pyi flake8-pytest flake8-pytest-style flake8-mutable flake8-string-format flake8-todo flake8-unused-arguments  # \u0442\u0435\u0441\u0442\u044b pytest <\/code><\/pre>\n<p>  \u0412\u044b\u0441\u043a\u0430\u0436\u0443 \u0441\u0432\u043e\u0435 \u043c\u043d\u0435\u043d\u0438\u0435 \u043f\u043e \u043f\u043e\u0432\u043e\u0434\u0443 flake-8 \u0438 \u043b\u0438\u043d\u0442\u0435\u0440\u043e\u0432 \u0432 \u0446\u0435\u043b\u043e\u043c. \u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0443\u0436\u0435 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 \u043a\u0443\u0447\u0435\u0439 legacy \u043a\u043e\u0434\u0430, \u0442\u043e \u043c\u043e\u0436\u0435\u0442\u0435 \u043b\u0438\u043d\u0442\u0435\u0440\u044b \u0441\u043c\u0435\u043b\u043e \u0443\u0434\u0430\u043b\u044f\u0442\u044c. \u0417\u0430\u0442\u0440\u0430\u0442\u044b \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u0442\u0440\u0430\u0447\u0435\u043d\u044b \u043d\u0430 \u00ab\u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043a \u0438\u0434\u0435\u0430\u043b\u0443\u00bb, \u043d\u0430\u0447\u0430\u043b\u044c\u0441\u0442\u0432\u043e \u043d\u0435 \u043e\u0446\u0435\u043d\u0438\u0442. \u041b\u0438\u043d\u0442\u0435\u0440\u044b \u0441\u0442\u0430\u0432\u0438\u043c \u0434\u043b\u044f \u043d\u043e\u0432\u044b\u0445 (\u0438 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0445) \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432. \u041f\u043e\u0432\u0442\u043e\u0440\u044e\u0441\u044c, \u044d\u0442\u043e \u043b\u0438\u0447\u043d\u043e \u043c\u043e\u0435 \u043c\u043d\u0435\u043d\u0438\u0435, \u043d\u0438\u043a\u043e\u043c\u0443 \u0435\u0433\u043e \u043d\u0435 \u043d\u0430\u0432\u044f\u0437\u044b\u0432\u0430\u044e.<\/p>\n<h3>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0432 \u0441\u0440\u0435\u0434\u0443<\/h3>\n<p>  \u0417\u0430\u0445\u043e\u0434\u0438\u043c \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u0441\u0440\u0435\u0434\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b<\/p>\n<pre><code class=\"bash\">$ pre-commit install pre-commit installed at .git\/hooks\/pre-commit $ pre-commit --version pre-commit 2.4.0 <\/code><\/pre>\n<blockquote><p>\u0415\u0441\u043b\u0438 .pre-commit \u0431\u0443\u0434\u0435\u0442 \u0440\u0443\u0433\u0430\u0442\u044c\u0441\u044f \u043d\u0430 sqlite, \u0442\u043e \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0435\u0433\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c (\u043a \u043f\u0440\u0438\u043c\u0435\u0440\u0443 $ yum install sqlite) \u0438 \u0441\u043e\u0431\u0440\u0430\u0442\u044c python \u0437\u0430\u043d\u043e\u0432\u043e<\/p><\/blockquote>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0444\u0430\u0439\u043b\u0430 .pre-commit-config.yaml<\/h3>\n<p>  \u0412 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 \u0441\u0440\u0435\u0434\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0444\u0430\u0439\u043b .pre-commit-config.yaml<\/p>\n<pre><code class=\"python\">- repo: https:\/\/github.com\/pre-commit\/pre-commit-hooks   rev: &quot;v2.5.0&quot;   hooks:     - id: check-merge-conflict     - id: debug-statements  - repo: local    hooks:     - id: black       name: black       entry: black       language: system       types: [python]       args: [--line-length=200, --target-version=py37]      - id: autoflake       name: autoflake       entry: autoflake       language: system       types: [python]       args: [--in-place, --remove-all-unused-imports, --remove-duplicate-keys]      # -   id: flake8     #     name: flake8     #     entry: flake8     #     language: system     #     types: [python]     #     args: [     #         &quot;--ignore=E203,W503,FI10,FI11,FI12,FI13,FI14,FI15,FI16,FI17,FI58,PT013&quot;,     #         # black     #             # E203 whitespace before ':'     #             # W503 line break before binary operator     #         # flake8-future-import     #             # FI10 __future__ import &quot;division&quot; missing     #             # FI11 __future__ import &quot;absolute_import&quot; missing     #             # FI12 __future__ import &quot;with_statement&quot; missing     #             # FI13 __future__ import &quot;print_function&quot; missing     #             # FI14 __future__ import &quot;unicode_literals&quot; missing     #             # FI15 __future__ import &quot;generator_stop&quot; missing     #             # FI16 __future__ import &quot;nested_scopes&quot; missing     #             # FI17 __future__ import &quot;generators&quot; missing     #             # FI58 __future__ import &quot;annotations&quot; present     #         # flake8-pytest-style     #             # PT013 found incorrect import of pytest, use simple 'import pytest' instead     #         &quot;--max-line-length=110&quot;,     #         &quot;--per-file-ignores=tests\/*.py:S101&quot;     #         # S101 Use of assert detected     #     ]      - id: pyupgrade       name: pyupgrade       entry: pyupgrade       language: system       types: [python]       args: [--py37-plus]      - id: reorder-python-imports       name: reorder-python-imports       entry: reorder-python-imports       language: system       types: [python]       args: [--py37-plus]      - id: yesqa       name: yesqa       entry: yesqa       language: system       types: [python]      - id: tests       name: Run tests       entry: &quot;bash tests.sh&quot;       language: system       verbose: true  <\/code><\/pre>\n<h3>\u0422\u0435\u0441\u0442\u044b<\/h3>\n<p>  \u041f\u043e\u043c\u0438\u043c\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0442\u0435\u0441\u0442\u044b \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043a\u043e\u043c\u043c\u0438\u0442\u0430. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c pytest (https:\/\/docs.pytest.org\/en\/latest\/) \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0435\u0433\u043e \u0434\u043b\u044f \u043d\u0430\u0448\u0438\u0445 \u043d\u0443\u0436\u0434.<\/p>\n<p>  \u0412 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 \u0441\u0440\u0435\u0434\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0430\u043f\u043a\u0443 tests \u0438 \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u043c \u0442\u0443\u0434\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0444\u0430\u0439\u043b\u044b<br \/>  test_example_without_db.py, test_example_with_db.py<\/p>\n<p>  \u0414\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0442\u0435\u0441\u0442\u044b \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 (\u043a \u043f\u0440\u0438\u043c\u0435\u0440\u0443 \u043a\u043e\u043f\u0438\u044e \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0441 \u0431\u043e\u0435\u0432\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430), \u0430 \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u043d\u043e\u0432\u0443\u044e. <\/p>\n<p>  \u041f\u0440\u043e\u0441\u0442\u043e\u0439 \u0442\u0435\u0441\u0442 <b>test_example_without_db.py <\/b><\/p>\n<pre><code class=\"python\">def inc(x):     return x + 1  def test_answer():     assert inc(3) == 4 <\/code><\/pre>\n<p>  \u0412 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0442\u0435\u0441\u0442\u0430\u0445 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 webbot (https:\/\/pypi.org\/project\/webbot\/) \u0438 \u043e\u0431\u0445\u043e\u0434\u0438\u0442\u044c \u0443\u0437\u043b\u044b \u043d\u0430\u0448\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b, \u0447\u0442\u043e\u0431\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0443\u0447\u043d\u043e\u0439 \u0442\u0440\u0443\u0434 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0430.<\/p>\n<p>  \u0422\u0435\u0441\u0442 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 <b>test_example_with_db.py <\/b><\/p>\n<pre><code class=\"python\">import pytest from chat.models import ChatRoom from settings import POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD, \\                     POSTGRES_HOST, POSTGRES_PORT  @pytest.fixture(scope='session') def django_db_setup():     settings.DATABASES['default'] = {         'ENGINE': 'django.db.backends.postgresql_psycopg2',         'NAME': POSTGRES_DB,         'USER': POSTGRES_USER,         'PASSWORD': POSTGRES_PASSWORD,         'HOST': POSTGRES_HOST,         'PORT': POSTGRES_PORT,     }              @pytest.fixture def db_access_without_rollback_and_truncate(request, django_db_setup, django_db_blocker):     django_db_blocker.unblock()     request.addfinalizer(django_db_blocker.restore)  def chat():     return ChatRoom.objects.all().count()  @pytest.mark.django_db def test_chat():     assert chat() &gt; 0 <\/code><\/pre>\n<p>  \u041f\u0440\u0438\u043c\u0435\u0440 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0438\u0441\u043a\u0443\u0441\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0438 \u0441\u043e\u0437\u0434\u0430\u043d \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0439 \u0437\u0430\u043c\u0435\u0442\u043a\u0438, \u043d\u043e \u0442\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 \u043e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043a \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u0438 \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b\u0445\u043e\u0434\u044f\u0442 \u0437\u0430 \u0440\u0430\u043c\u043a\u0438 \u0440\u0443\u0447\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<h3>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0442\u0435\u0441\u0442\u044b \u0432 .pre-commit<\/h3>\n<p>  \u0427\u0442\u043e\u0431\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0442\u0435\u0441\u0442\u044b \u043d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f shell script \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 \u0441\u0440\u0435\u0434\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u043d\u0430\u0437\u043e\u0432\u0435\u043c tests.sh<\/p>\n<pre><code class=\"python\">source ..\/..\/python38_env\/bin\/activate &amp;&amp; python -m pytest -v tests <\/code><\/pre>\n<p>  \u0415\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0432\u0435\u0441\u044c\u043c\u0430 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e\u0435, \u043d\u043e \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c \u0447\u0442\u043e \u0430\u043a\u0442\u0438\u0432\u0430\u0446\u0438\u044f \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u044f\u0432\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043f\u0440\u043e\u043f\u0438\u0441\u0430\u043d\u0430 \u0432 \u043a\u043e\u0434\u0435. \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0435\u0443\u0434\u043e\u0431\u043d\u043e, \u0435\u0441\u043b\u0438 \u0432\u0430\u0448\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0432\u0435\u0434\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0445 \u0440\u0430\u0431\u043e\u0447\u0438\u0445 \u0441\u0442\u0430\u043d\u0446\u0438\u044f\u0445 (\u043a \u043f\u0440\u0438\u043c\u0435\u0440\u0443 \u043a\u0442\u043e \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u043b \u0441\u0440\u0435\u0434\u0443 \u043d\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435, \u0430 \u043a\u0442\u043e-\u0442\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435).<\/p>\n<p>  \u041c\u043e\u0436\u043d\u043e \u0440\u0435\u0448\u0438\u0442\u044c \u044d\u0442\u0443 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0447\u0435\u0440\u0435\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0432 .env<br \/>  \u041f\u0440\u0438\u043c\u0435\u0440 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438:<br \/>  <a href=\"https:\/\/github.com\/Sobolev5\/starlette-vue-backend\/blob\/master\/.env.example\" rel=\"nofollow\">github.com\/Sobolev5\/starlette-vue-backend\/blob\/master\/.env.example<\/a> (\u043e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e ENV_ACTIVATE)<br \/>  <a href=\"https:\/\/github.com\/Sobolev5\/starlette-vue-backend\/blob\/master\/tests.sh\" rel=\"nofollow\">github.com\/Sobolev5\/starlette-vue-backend\/blob\/master\/tests.sh<\/a> (\u043f\u0430\u0440\u0441\u0438\u043c ENV_ACTIVATE \u0438 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0443\u0435\u043c \u0441\u0440\u0435\u0434\u0443)<\/p>\n<h3>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043a\u043e\u043c\u043c\u0438\u0442<\/h3>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043e\u043c\u043c\u0438\u0442 \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043a\u0430\u043a \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442<\/p>\n<pre><code class=\"python\">$ git add . $ git commit -m Sobolev:TestPreCommitHook Check for merge conflicts................................................Passed Debug Statements (Python)................................................Passed black....................................................................Failed - hook id: black - files were modified by this hook  reformatted \/var\/www\/file.py All done!    1 file reformatted, 2 files left unchanged.  autoflake................................................................Passed pyupgrade................................................................Passed reorder-python-imports...................................................Failed - hook id: reorder-python-imports - exit code: 1 - files were modified by this hook  Reordering imports in file.py  yesqa....................................................................Passed Run tests................................................................Passed - hook id: tests - duration: 2.85s  tests\/test_example_with_db.py::test_chat PASSED                          [ 66%] tests\/test_example_without_db.py::test_answer PASSED                     [100%] <\/code><\/pre>\n<p>  \u041a\u043e\u043c\u043c\u0438\u0442 \u0442\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u0432 \u00ab\u0434\u0432\u0430 \u044d\u0442\u0430\u043f\u0430\u00bb. \u041d\u0430 \u043f\u0435\u0440\u0432\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u0445\u0443\u043a\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u0434\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u0441\u043b\u0435 \u0438\u0445 \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u00ab\u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c\u00bb \u043a\u043e\u043c\u0430\u043d\u0434\u044b.<br \/>  \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c.<\/p>\n<pre><code class=\"bash\">$ git add . $ git commit -m Sobolev:TestPreCommitHook $ git add . $ git commit -m Sobolev:TestPreCommitHook <\/code><\/pre>\n<p>  \u041d\u0430 \u044d\u0442\u043e\u043c \u0432\u0441\u0435, \u0441\u043f\u0430\u0441\u0438\u0431\u043e \u0437\u0430 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435. <\/p>\n<h3>\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438<\/h3>\n<p>  <a href=\"https:\/\/pre-commit.com\/hooks.html\" rel=\"nofollow\">pre-commit.com\/hooks.html<\/a> \u041f\u043e\u043b\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0445\u0443\u043a\u043e\u0432<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/503270\/\"> https:\/\/habr.com\/ru\/post\/503270\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/503270\/\">\u0414\u043e\u0431\u0440\u043e\u0433\u043e \u0434\u043d\u044f!<\/p>\n<p>  \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0421\u043e\u0431\u043e\u043b\u0435\u0432 \u0410\u043d\u0434\u0440\u0435\u0439 \u0438 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u044f \u0432\u0430\u043c \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043a\u0430\u043a \u043c\u044b \u043f\u0440\u0438\u0433\u043e\u0442\u043e\u0432\u0438\u043b\u0438 .pre-commit hook \u043d\u0430 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435.<\/p>\n<h3>\u0412\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0435<\/h3>\n<p>  \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0430\u0440\u0443 \u0441\u043b\u043e\u0432, \u043e \u0442\u043e\u043c \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0432 \u0446\u0435\u043b\u043e\u043c \u0445\u0443\u043a\u0438 (hooks) \u0438 \u0434\u043b\u044f \u0447\u0435\u0433\u043e \u043e\u043d\u0438 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u0443\u0436\u043d\u044b. Git \u00ab\u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438\u00bb \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u043c\u0435\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0432\u0430\u0448\u0438 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u043f\u0440\u0438 \u043d\u0430\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0438 \u043a\u0430\u043a\u043e\u0433\u043e \u043b\u0438\u0431\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044f (\u043a \u043f\u0440\u0438\u043c\u0435\u0440\u0443 \u043f\u0443\u0448 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0438 \u0442.\u043f.)<\/p>\n<p>  .pre-commit \u044d\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u0430\u044f \u043d\u0430\u0434\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043d\u0430\u0434 \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u043c git pre-commit hook, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u0432 .pre-commit-config.yaml \u043f\u0435\u0440\u0435\u0434 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435\u043c \u043a\u043e\u043c\u043c\u0438\u0442\u0430. \u0412 \u0442\u0435\u043e\u0440\u0438\u0438 \u0437\u0432\u0443\u0447\u0438\u0442 \u043f\u0440\u043e\u0441\u0442\u043e, \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-304057","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/304057","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=304057"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/304057\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=304057"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=304057"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=304057"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}