diff --git a/.coverage.conf b/.coverage.conf new file mode 100644 index 0000000..c41b23c --- /dev/null +++ b/.coverage.conf @@ -0,0 +1,2 @@ +[run] +omit = */tests/* \ No newline at end of file diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..538cd41 --- /dev/null +++ b/.flake8 @@ -0,0 +1,6 @@ +[flake8] +max-line-length = 99 +# E203 is incompatible with pep8 and makes black mad +extend-ignore = E203 +# Enforce using single quotes with flake8-quotes +inline-quotes = single diff --git a/.isort.cfg b/.isort.cfg new file mode 100644 index 0000000..b9d5939 --- /dev/null +++ b/.isort.cfg @@ -0,0 +1,4 @@ +[settings] +profile = black +multi_line_output = 3 +line_length = 99 diff --git a/.mypy.ini b/.mypy.ini new file mode 100644 index 0000000..1c239ce --- /dev/null +++ b/.mypy.ini @@ -0,0 +1,4 @@ +[mypy] +ignore_missing_imports = True +show_error_codes = True +plugins = pydantic.mypy diff --git a/Dockerfile b/Dockerfile index f44b8ea..aa74247 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,6 +24,9 @@ RUN echo "#!/bin/bash\n/python/entrypoint.sh startapp" >> /bin/startapp && chmod echo "#!/bin/bash\n/python/entrypoint.sh runtests" >> /bin/runtests && chmod a+x /bin/runtests &&\ pip install -r /python/requirements.txt +# Copy standard configurations for code validation +COPY pytest.ini .flake8 .isort.cfg .mypy.ini .coverage.conf /home/python/ + # Change users USER python diff --git a/README.md b/README.md index 2532c51..0f72be2 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,8 @@ such as the `entrypoint.sh`. Then the subfolders organize the app files: * `/python/static` holds the static files served by the app such as static html files * `/python/logs` is meant for the log files generated by the app * `/python/files` is for files uploaded through the app +* `/home/python` contains the [standard configuration files](Standard-configurations-for-code-quality) +for linting, formatting and other testing tools ## :toolbox: Notes for maintenance @@ -127,6 +129,9 @@ plugin. This code validation command executes the `/python/test_suite.sh` script which can be overwritten with custom code validation. +These code quality tools will follow the +[standard configurations](Standard-configurations-for-code-quality) present in `/home/python` +by default. ### `validatecodeonce` @@ -145,3 +150,17 @@ and code coverage results in the `/python/app/unittesting.xml` and A [coverage configuration file](https://pytest-cov.readthedocs.io/en/latest/config.html) can be provided at `python/app/coverage.conf`. + +## Standard configurations for code quality + +Standard configuration files for all the code quality tools are located in `/home/python` +where the tools will find them. +These configurations can be overwritten: + +* `mypy`: Add the configuration file `/python/app/.mypy.ini` and the standard file in +`/home/python` will be ignored. +* `flake8`: Add the configuration file `/python/app/.flake8` it will be *appended* to +the standard file in `/home/python`. Therefore to turn off all the configurations +in the standard file you must explicitely reverse them in the `/python/app/.flake8` file. +* `isort`: Add the configuration `/python/app/.isort.cfg` and the standard file in +`/home/python` will be ignored. diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..e69de29 diff --git a/test_suite.sh b/test_suite.sh index 94ed03b..f4715eb 100755 --- a/test_suite.sh +++ b/test_suite.sh @@ -27,26 +27,28 @@ reportvalidation() { if [[ $1 == "reports" ]] then MYPY_REPORTS="--junit-xml ${REPORTS_FOLDER}typing.xml" - if [ -f ./coverage.conf ]; - then - $covconf="--cov-config ./coverage.conf" - fi - PYTEST_REPORTS="--junitxml ${REPORTS_FOLDER}unittesting.xml $covconf --cov-report xml:${REPORTS_FOLDER}coverage.xml" + PYTEST_REPORTS="--junitxml ${REPORTS_FOLDER}unittesting.xml --cov-report xml:${REPORTS_FOLDER}coverage.xml" +fi + +COVERAGE_CONF="--cov-config /home/python/.coverage.conf" +if [ -f ./coverage.conf ]; +then + COVERAGE_CONF="--cov-config ./coverage.conf" fi echo -ne "$SECTION_PREFIX RUN TESTS:\n\n" -python -m pytest -vv --durations=3 --cov ./ --cov-report term-missing $PYTEST_REPORTS; STATUS1=$? +python -m pytest --rootdir=/python/app -vv --durations=3 --cov ./ --cov-report term-missing $COVERAGE_CONF $PYTEST_REPORTS; STATUS1=$? echo -ne "$SECTION_PREFIX CHECK DOCKER USER IS PYTHON: " USEROUT=`checkuser` reportvalidation "$USEROUT"; STATUS2=$? echo -ne "$SECTION_PREFIX CHECK TYPING: " -MYPYOUT=`mypy --no-error-summary . $MYPY_REPORTS` +MYPYOUT=`mypy --cache-dir /home/python --no-error-summary . $MYPY_REPORTS` reportvalidation "$MYPYOUT"; STATUS3=$? echo -ne "$SECTION_PREFIX CHECK LINTING: " -FLAKE8OUT=`flake8` +FLAKE8OUT=`flake8 --append-config /home/python/.flake8 --append-config /python/app/.flake8` reportvalidation "$FLAKE8OUT"; STATUS4=$? echo -ne "$SECTION_PREFIX CHECK FORMATTING: " diff --git a/tests/.flake8 b/tests/.flake8 new file mode 100644 index 0000000..8952d12 --- /dev/null +++ b/tests/.flake8 @@ -0,0 +1,3 @@ +[flake8] +# FOR TEST PURPOSES ONLY +extend-ignore = F401 diff --git a/tests/webapp/main.py b/tests/webapp/main.py index 678aff5..ef80c72 100644 --- a/tests/webapp/main.py +++ b/tests/webapp/main.py @@ -1,3 +1,8 @@ +# FLAKE8: This would trigger an F401 error without the local .flake8 +from math import tan + +# MYPY: This import triggers a missing import error without the standard config +# file from fastapi import FastAPI app = FastAPI() @@ -6,3 +11,10 @@ @app.get('/') async def root(): return {'message': 'Hello World'} + + +def dummy_func(): + # FLAKE8: The following two lines would trigger an E501 flake8 error + # without the standard config in /home/python + this_is_a_very_long_variable_name_used_to_test_the_flake8_standard_config = 'ok' + return this_is_a_very_long_variable_name_used_to_test_the_flake8_standard_config diff --git a/tests/webapp/tests/simple_test.py b/tests/webapp/tests/simple_test.py index 9da8a08..a9550ef 100644 --- a/tests/webapp/tests/simple_test.py +++ b/tests/webapp/tests/simple_test.py @@ -1,2 +1,5 @@ -def test_something(): - assert True +from webapp.main import dummy_func + + +def test_dummy_func(): + assert dummy_func() == 'ok'