diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000000..48bac2f2003 --- /dev/null +++ b/.flake8 @@ -0,0 +1,5 @@ +# TODO: move this to pyproject.toml when supported: https://gitlab.com/pycqa/flake8/merge_requests/245 + +[flake8] +max-line-length = 120 +ignore = E741 diff --git a/.github/workflows/python-lint.yaml b/.github/workflows/python-lint.yaml new file mode 100644 index 00000000000..ca0e813bfc6 --- /dev/null +++ b/.github/workflows/python-lint.yaml @@ -0,0 +1,39 @@ +name: "Lints Python code" + +on: + push: + branches: + - master + paths: + - "**.py" + - ".flake8" + pull_request: + paths: + - "**.py" + - ".flake8" + +jobs: + python-linting: + name: "Lints Python code" + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@master + + - name: Install Taskfile + uses: Arduino/actions/setup-taskfile@master + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Activate Python + uses: actions/setup-python@v1 + with: + python-version: '3.8' + architecture: 'x64' + + - name: Install Poetry + run: pip install poetry + + - name: Lints Python files + run: task python:check diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 0f22be6cd4e..dc5dc922857 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -43,6 +43,15 @@ jobs: with: repo-token: ${{ secrets.GITHUB_TOKEN }} + - name: Install Python + uses: actions/setup-python@v1 + with: + python-version: "3.8" + architecture: "x64" + + - name: Install Poetry + run: pip install poetry + - name: Check the code is good run: task check @@ -65,16 +74,8 @@ jobs: if: matrix.operating-system == 'ubuntu-latest' run: task test-legacy - - name: Install Python - uses: actions/setup-python@v1 - with: - python-version: '3.8' - architecture: 'x64' - - name: Run integration tests - run: | - pip install poetry - task test-integration + run: task test-integration - name: Send unit tests coverage to Codecov # Since secrets aren't available on forks, we only diff --git a/Taskfile.yml b/Taskfile.yml index 3ee38d2005a..6865ded6433 100755 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -104,6 +104,19 @@ tasks: - go vet {{ default .DEFAULT_TARGETS .TARGETS }} - "'{{.GOLINTBIN}}' {{.GOLINTFLAGS}} {{ default .DEFAULT_TARGETS .TARGETS }}" - task: i18n:check + - task: python:check + + python:check: + desc: Linting for Python files + cmds: + - poetry install --no-root + - poetry run flake8 + + python:format: + desc: Automatically formats Python files + cmds: + - poetry install --no-root + - poetry run black . check-legacy: desc: Check fmt and lint for the `legacy` package diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 296036a6503..bbf2e35a7dc 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -154,6 +154,20 @@ task test-integration This will automatically install the necessary dependencies, if not already installed, and run the integration tests automatically. +When editing any Python file in the project remember to run linting checks with: + +```shell +task python:check +``` + +This will run `flake8` automatically and return any error in the code formatting, if not already installed it will also install integration tests dependencies. + +In case of linting errors you should be able to solve most of them by automatically formatting with: + +```shell +task python:format +``` + ## Working on docs Documentation is provided to final users in form of static HTML content generated diff --git a/docs/build.py b/docs/build.py index d258024c317..a8805fdc7ba 100644 --- a/docs/build.py +++ b/docs/build.py @@ -100,15 +100,11 @@ def main(test, dry, remote): # version is the most recent docs_version, alias = get_docs_version(repo.active_branch.name, rel_br_names) if docs_version is None: - print( - f"Can't get version from current branch '{repo.active_branch}', skip docs generation" - ) + print(f"Can't get version from current branch '{repo.active_branch}', skip docs generation") return 0 # Taskfile args aren't regular args so we put everything in one string - cmd = ( - f"task docs:publish DOCS_REMOTE={remote} DOCS_VERSION={docs_version} DOCS_ALIAS={alias}", - ) + cmd = (f"task docs:publish DOCS_REMOTE={remote} DOCS_VERSION={docs_version} DOCS_ALIAS={alias}",) if dry: print(cmd) diff --git a/poetry.lock b/poetry.lock index 837adda5ef1..46715ebc2c8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,3 +1,11 @@ +[[package]] +category = "main" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +name = "appdirs" +optional = false +python-versions = "*" +version = "1.4.4" + [[package]] category = "main" description = "Atomic file writes." @@ -21,6 +29,26 @@ dev = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.int docs = ["sphinx", "zope.interface"] tests = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] +[[package]] +category = "main" +description = "The uncompromising code formatter." +name = "black" +optional = false +python-versions = ">=3.6" +version = "19.10b0" + +[package.dependencies] +appdirs = "*" +attrs = ">=18.1.0" +click = ">=6.5" +pathspec = ">=0.6,<1" +regex = "*" +toml = ">=0.9.4" +typed-ast = ">=1.4.0" + +[package.extras] +d = ["aiohttp (>=3.3.2)", "aiohttp-cors"] + [[package]] category = "main" description = "Python package for providing Mozilla's CA Bundle." @@ -37,6 +65,14 @@ optional = false python-versions = "*" version = "3.0.4" +[[package]] +category = "main" +description = "Composable command line interface toolkit" +name = "click" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "7.1.2" + [[package]] category = "main" description = "Cross-platform colored terminal text." @@ -46,6 +82,19 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" version = "0.4.3" +[[package]] +category = "main" +description = "the modular source code checker: pep8 pyflakes and co" +name = "flake8" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" +version = "3.8.3" + +[package.dependencies] +mccabe = ">=0.6.0,<0.7.0" +pycodestyle = ">=2.6.0a1,<2.7.0" +pyflakes = ">=2.2.0,<2.3.0" + [[package]] category = "main" description = "Internationalized Domain Names in Applications (IDNA)" @@ -56,27 +105,19 @@ version = "2.8" [[package]] category = "main" -description = "Read metadata from Python packages" -marker = "python_version < \"3.8\"" -name = "importlib-metadata" +description = "Pythonic task execution" +name = "invoke" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -version = "1.7.0" - -[package.dependencies] -zipp = ">=0.5" - -[package.extras] -docs = ["sphinx", "rst.linker"] -testing = ["packaging", "pep517", "importlib-resources (>=1.3)"] +python-versions = "*" +version = "1.4.1" [[package]] category = "main" -description = "Pythonic task execution" -name = "invoke" +description = "McCabe checker, plugin for flake8" +name = "mccabe" optional = false python-versions = "*" -version = "1.4.1" +version = "0.6.1" [[package]] category = "main" @@ -100,15 +141,11 @@ six = "*" [[package]] category = "main" -description = "Object-oriented filesystem paths" -marker = "python_version < \"3.6\"" -name = "pathlib2" +description = "Utility library for gitignore style pattern matching of file paths." +name = "pathspec" optional = false -python-versions = "*" -version = "2.3.5" - -[package.dependencies] -six = "*" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "0.8.0" [[package]] category = "main" @@ -118,11 +155,6 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" version = "0.13.1" -[package.dependencies] -[package.dependencies.importlib-metadata] -python = "<3.8" -version = ">=0.12" - [package.extras] dev = ["pre-commit", "tox"] @@ -145,6 +177,22 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" version = "1.9.0" +[[package]] +category = "main" +description = "Python style guide checker" +name = "pycodestyle" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.6.0" + +[[package]] +category = "main" +description = "passive checker of Python programs" +name = "pyflakes" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.2.0" + [[package]] category = "main" description = "Python parsing module" @@ -179,14 +227,6 @@ pluggy = ">=0.12,<1.0" py = ">=1.5.0" wcwidth = "*" -[package.dependencies.importlib-metadata] -python = "<3.8" -version = ">=0.12" - -[package.dependencies.pathlib2] -python = "<3.6" -version = ">=2.2.0" - [package.extras] checkqa-mypy = ["mypy (v0.761)"] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] @@ -210,6 +250,14 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" version = "5.3" +[[package]] +category = "main" +description = "Alternative regular expression module, to replace re." +name = "regex" +optional = false +python-versions = "*" +version = "2020.7.14" + [[package]] category = "main" description = "Python HTTP for Humans." @@ -252,6 +300,22 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" version = "1.15.0" +[[package]] +category = "main" +description = "Python Library for Tom's Obvious, Minimal Language" +name = "toml" +optional = false +python-versions = "*" +version = "0.10.1" + +[[package]] +category = "main" +description = "a fork of Python 2 and 3 ast modules with type comment support" +name = "typed-ast" +optional = false +python-versions = "*" +version = "1.4.1" + [[package]] category = "main" description = "HTTP library with thread-safe connection pooling, file post, and more." @@ -273,24 +337,15 @@ optional = false python-versions = "*" version = "0.2.5" -[[package]] -category = "main" -description = "Backport of pathlib-compatible object wrapper for zip files" -marker = "python_version < \"3.8\"" -name = "zipp" -optional = false -python-versions = ">=2.7" -version = "1.2.0" - -[package.extras] -docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] -testing = ["pathlib2", "unittest2", "jaraco.itertools", "func-timeout"] - [metadata] -content-hash = "d67de1cfb1e5332ad1ce698ac0dd5118d5254c86da7c1643a4428bd2f082df41" -python-versions = "^3.5" +content-hash = "f28e76c2cd84157e665d2d1bcd6c12e83d9deecc196fcc5e5e74e27fa072fd4d" +python-versions = "^3.8" [metadata.files] +appdirs = [ + {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, + {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, +] atomicwrites = [ {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, @@ -299,6 +354,10 @@ attrs = [ {file = "attrs-19.3.0-py2.py3-none-any.whl", hash = "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c"}, {file = "attrs-19.3.0.tar.gz", hash = "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"}, ] +black = [ + {file = "black-19.10b0-py36-none-any.whl", hash = "sha256:1b30e59be925fafc1ee4565e5e08abef6b03fe455102883820fe5ee2e4734e0b"}, + {file = "black-19.10b0.tar.gz", hash = "sha256:c2edb73a08e9e0e6f65a0e6af18b059b8b1cdd5bef997d7a0b181df93dc81539"}, +] certifi = [ {file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"}, {file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"}, @@ -307,23 +366,31 @@ chardet = [ {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, ] +click = [ + {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"}, + {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"}, +] colorama = [ {file = "colorama-0.4.3-py2.py3-none-any.whl", hash = "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff"}, {file = "colorama-0.4.3.tar.gz", hash = "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1"}, ] +flake8 = [ + {file = "flake8-3.8.3-py2.py3-none-any.whl", hash = "sha256:15e351d19611c887e482fb960eae4d44845013cc142d42896e9862f775d8cf5c"}, + {file = "flake8-3.8.3.tar.gz", hash = "sha256:f04b9fcbac03b0a3e58c0ab3a0ecc462e023a9faf046d57794184028123aa208"}, +] idna = [ {file = "idna-2.8-py2.py3-none-any.whl", hash = "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"}, {file = "idna-2.8.tar.gz", hash = "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407"}, ] -importlib-metadata = [ - {file = "importlib_metadata-1.7.0-py2.py3-none-any.whl", hash = "sha256:dc15b2969b4ce36305c51eebe62d418ac7791e9a157911d58bfb1f9ccd8e2070"}, - {file = "importlib_metadata-1.7.0.tar.gz", hash = "sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83"}, -] invoke = [ {file = "invoke-1.4.1-py2-none-any.whl", hash = "sha256:93e12876d88130c8e0d7fd6618dd5387d6b36da55ad541481dfa5e001656f134"}, {file = "invoke-1.4.1-py3-none-any.whl", hash = "sha256:87b3ef9d72a1667e104f89b159eaf8a514dbf2f3576885b2bbdefe74c3fb2132"}, {file = "invoke-1.4.1.tar.gz", hash = "sha256:de3f23bfe669e3db1085789fd859eb8ca8e0c5d9c20811e2407fa042e8a5e15d"}, ] +mccabe = [ + {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, + {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, +] more-itertools = [ {file = "more-itertools-8.4.0.tar.gz", hash = "sha256:68c70cc7167bdf5c7c9d8f6954a7837089c6a36bf565383919bb595efb8a17e5"}, {file = "more_itertools-8.4.0-py3-none-any.whl", hash = "sha256:b78134b2063dd214000685165d81c154522c3ee0a1c0d4d113c80361c234c5a2"}, @@ -332,9 +399,9 @@ packaging = [ {file = "packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"}, {file = "packaging-20.4.tar.gz", hash = "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8"}, ] -pathlib2 = [ - {file = "pathlib2-2.3.5-py2.py3-none-any.whl", hash = "sha256:0ec8205a157c80d7acc301c0b18fbd5d44fe655968f5d947b6ecef5290fc35db"}, - {file = "pathlib2-2.3.5.tar.gz", hash = "sha256:6cd9a47b597b37cc57de1c05e56fb1a1c9cc9fab04fe78c29acd090418529868"}, +pathspec = [ + {file = "pathspec-0.8.0-py2.py3-none-any.whl", hash = "sha256:7d91249d21749788d07a2d0f94147accd8f845507400749ea19c1ec9054a12b0"}, + {file = "pathspec-0.8.0.tar.gz", hash = "sha256:da45173eb3a6f2a5a487efba21f050af2b41948be6ab52b6a1e3ff22bb8b7061"}, ] pluggy = [ {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, @@ -347,6 +414,14 @@ py = [ {file = "py-1.9.0-py2.py3-none-any.whl", hash = "sha256:366389d1db726cd2fcfc79732e75410e5fe4d31db13692115529d34069a043c2"}, {file = "py-1.9.0.tar.gz", hash = "sha256:9ca6883ce56b4e8da7e79ac18787889fa5206c79dcc67fb065376cd2fe03f342"}, ] +pycodestyle = [ + {file = "pycodestyle-2.6.0-py2.py3-none-any.whl", hash = "sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367"}, + {file = "pycodestyle-2.6.0.tar.gz", hash = "sha256:c58a7d2815e0e8d7972bf1803331fb0152f867bd89adf8a01dfd55085434192e"}, +] +pyflakes = [ + {file = "pyflakes-2.2.0-py2.py3-none-any.whl", hash = "sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92"}, + {file = "pyflakes-2.2.0.tar.gz", hash = "sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8"}, +] pyparsing = [ {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, @@ -376,6 +451,29 @@ pyyaml = [ {file = "PyYAML-5.3-cp38-cp38-win_amd64.whl", hash = "sha256:cb1f2f5e426dc9f07a7681419fe39cee823bb74f723f36f70399123f439e9b20"}, {file = "PyYAML-5.3.tar.gz", hash = "sha256:e9f45bd5b92c7974e59bcd2dcc8631a6b6cc380a904725fce7bc08872e691615"}, ] +regex = [ + {file = "regex-2020.7.14-cp27-cp27m-win32.whl", hash = "sha256:e46d13f38cfcbb79bfdb2964b0fe12561fe633caf964a77a5f8d4e45fe5d2ef7"}, + {file = "regex-2020.7.14-cp27-cp27m-win_amd64.whl", hash = "sha256:6961548bba529cac7c07af2fd4d527c5b91bb8fe18995fed6044ac22b3d14644"}, + {file = "regex-2020.7.14-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:c50a724d136ec10d920661f1442e4a8b010a4fe5aebd65e0c2241ea41dbe93dc"}, + {file = "regex-2020.7.14-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8a51f2c6d1f884e98846a0a9021ff6861bdb98457879f412fdc2b42d14494067"}, + {file = "regex-2020.7.14-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:9c568495e35599625f7b999774e29e8d6b01a6fb684d77dee1f56d41b11b40cd"}, + {file = "regex-2020.7.14-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:51178c738d559a2d1071ce0b0f56e57eb315bcf8f7d4cf127674b533e3101f88"}, + {file = "regex-2020.7.14-cp36-cp36m-win32.whl", hash = "sha256:9eddaafb3c48e0900690c1727fba226c4804b8e6127ea409689c3bb492d06de4"}, + {file = "regex-2020.7.14-cp36-cp36m-win_amd64.whl", hash = "sha256:14a53646369157baa0499513f96091eb70382eb50b2c82393d17d7ec81b7b85f"}, + {file = "regex-2020.7.14-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:1269fef3167bb52631ad4fa7dd27bf635d5a0790b8e6222065d42e91bede4162"}, + {file = "regex-2020.7.14-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d0a5095d52b90ff38592bbdc2644f17c6d495762edf47d876049cfd2968fbccf"}, + {file = "regex-2020.7.14-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:4c037fd14c5f4e308b8370b447b469ca10e69427966527edcab07f52d88388f7"}, + {file = "regex-2020.7.14-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:bc3d98f621898b4a9bc7fecc00513eec8f40b5b83913d74ccb445f037d58cd89"}, + {file = "regex-2020.7.14-cp37-cp37m-win32.whl", hash = "sha256:46bac5ca10fb748d6c55843a931855e2727a7a22584f302dd9bb1506e69f83f6"}, + {file = "regex-2020.7.14-cp37-cp37m-win_amd64.whl", hash = "sha256:0dc64ee3f33cd7899f79a8d788abfbec168410be356ed9bd30bbd3f0a23a7204"}, + {file = "regex-2020.7.14-cp38-cp38-manylinux1_i686.whl", hash = "sha256:5ea81ea3dbd6767873c611687141ec7b06ed8bab43f68fad5b7be184a920dc99"}, + {file = "regex-2020.7.14-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:bbb332d45b32df41200380fff14712cb6093b61bd142272a10b16778c418e98e"}, + {file = "regex-2020.7.14-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:c11d6033115dc4887c456565303f540c44197f4fc1a2bfb192224a301534888e"}, + {file = "regex-2020.7.14-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:75aaa27aa521a182824d89e5ab0a1d16ca207318a6b65042b046053cfc8ed07a"}, + {file = "regex-2020.7.14-cp38-cp38-win32.whl", hash = "sha256:d6cff2276e502b86a25fd10c2a96973fdb45c7a977dca2138d661417f3728341"}, + {file = "regex-2020.7.14-cp38-cp38-win_amd64.whl", hash = "sha256:7a2dd66d2d4df34fa82c9dc85657c5e019b87932019947faece7983f2089a840"}, + {file = "regex-2020.7.14.tar.gz", hash = "sha256:3a3af27a8d23143c49a3420efe5b3f8cf1a48c6fc8bc6856b03f638abc1833bb"}, +] requests = [ {file = "requests-2.22.0-py2.py3-none-any.whl", hash = "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"}, {file = "requests-2.22.0.tar.gz", hash = "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4"}, @@ -418,6 +516,33 @@ six = [ {file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"}, {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"}, ] +toml = [ + {file = "toml-0.10.1-py2.py3-none-any.whl", hash = "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"}, + {file = "toml-0.10.1.tar.gz", hash = "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f"}, +] +typed-ast = [ + {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3"}, + {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb"}, + {file = "typed_ast-1.4.1-cp35-cp35m-win32.whl", hash = "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919"}, + {file = "typed_ast-1.4.1-cp35-cp35m-win_amd64.whl", hash = "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01"}, + {file = "typed_ast-1.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75"}, + {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652"}, + {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"}, + {file = "typed_ast-1.4.1-cp36-cp36m-win32.whl", hash = "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1"}, + {file = "typed_ast-1.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa"}, + {file = "typed_ast-1.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614"}, + {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41"}, + {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b"}, + {file = "typed_ast-1.4.1-cp37-cp37m-win32.whl", hash = "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe"}, + {file = "typed_ast-1.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355"}, + {file = "typed_ast-1.4.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6"}, + {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907"}, + {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d"}, + {file = "typed_ast-1.4.1-cp38-cp38-win32.whl", hash = "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c"}, + {file = "typed_ast-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4"}, + {file = "typed_ast-1.4.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34"}, + {file = "typed_ast-1.4.1.tar.gz", hash = "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b"}, +] urllib3 = [ {file = "urllib3-1.25.9-py2.py3-none-any.whl", hash = "sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115"}, {file = "urllib3-1.25.9.tar.gz", hash = "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527"}, @@ -426,7 +551,3 @@ wcwidth = [ {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, ] -zipp = [ - {file = "zipp-1.2.0-py2.py3-none-any.whl", hash = "sha256:e0d9e63797e483a30d27e09fffd308c59a700d365ec34e93cc100844168bf921"}, - {file = "zipp-1.2.0.tar.gz", hash = "sha256:c70410551488251b0fee67b460fb9a536af8d6f9f008ad10ac51f615b6a521b1"}, -] diff --git a/pyproject.toml b/pyproject.toml index 0f46dfc1ae9..210d24101b3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ description = "Project used to run integration tests for the Arduino CLI" authors = [] [tool.poetry.dependencies] -python = "^3.5" +python = "^3.8" pytest = "5.3.4" simplejson = "3.17.0" semver = "2.9.0" @@ -15,6 +15,9 @@ prometheus-client = "0.7.1" requests = "2.22.0" pytest-timeout = "1.3.4" invoke = "1.4.1" +flake8 = "^3.8.3" +black = { version = "^19.10b0", allow-prereleases = true } -[tool.flake8] -max-line-length = 120 +[tool.black] +line-length = 120 +target-version = ["py38"] diff --git a/test/README.md b/test/README.md index 3151e07f451..2ac0c32b889 100644 --- a/test/README.md +++ b/test/README.md @@ -46,6 +46,22 @@ pytest test_lib.py pytest test_lib.py::test_list ``` +## Linting and formatting + +To run lint check from the project's root folder: + +```shell +task python:check +``` + +This will run `flake8` automatically and return any error in the code formatting, if not already installed it will also install integration tests dependencies. + +In case of linting errors you should be able to solve most of them by automatically formatting with: + +```shell +task python:format +``` + [0]: ../docs/CONTRIBUTING.md [poetry-website]: https://python-poetry.org/ [poetry-docs]: https://python-poetry.org/docs/ diff --git a/test/conftest.py b/test/conftest.py index 773573368f4..5a1aab3b9fd 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -41,12 +41,12 @@ def data_dir(tmpdir_factory): # 3) libraries requiring headers deep down the include path # for example: # - # from C:\Users\runneradmin\AppData\Local\Temp\pytest-of-runneradmin\pytest-0\A7\packages\arduino\hardware\mbed\1.1.4\cores\arduino/mbed/rtos/Thread.h:29, - # from C:\Users\runneradmin\AppData\Local\Temp\pytest-of-runneradmin\pytest-0\A7\packages\arduino\hardware\mbed\1.1.4\cores\arduino/mbed/rtos/rtos.h:28, - # from C:\Users\runneradmin\AppData\Local\Temp\pytest-of-runneradmin\pytest-0\A7\packages\arduino\hardware\mbed\1.1.4\cores\arduino/mbed/mbed.h:23, - # from C:\Users\runneradmin\AppData\Local\Temp\pytest-of-runneradmin\pytest-0\A7\packages\arduino\hardware\mbed\1.1.4\cores\arduino/Arduino.h:32, - # from C:\Users\RUNNER~1\AppData\Local\Temp\arduino-sketch-739B2B6DD21EB014317DA2A46062811B\sketch\magic_wand.ino.cpp:1: - ##[error]c:\users\runneradmin\appdata\local\temp\pytest-of-runneradmin\pytest-0\a7\packages\arduino\tools\arm-none-eabi-gcc\7-2017q4\arm-none-eabi\include\c++\7.2.1\new:39:10: fatal error: bits/c++config.h: No such file or directory + # from C:\Users\runneradmin\AppData\Local\Temp\pytest-of-runneradmin\pytest-0\A7\packages\arduino\hardware\mbed\1.1.4\cores\arduino/mbed/rtos/Thread.h:29, # noqa: E501 + # from C:\Users\runneradmin\AppData\Local\Temp\pytest-of-runneradmin\pytest-0\A7\packages\arduino\hardware\mbed\1.1.4\cores\arduino/mbed/rtos/rtos.h:28, # noqa: E501 + # from C:\Users\runneradmin\AppData\Local\Temp\pytest-of-runneradmin\pytest-0\A7\packages\arduino\hardware\mbed\1.1.4\cores\arduino/mbed/mbed.h:23, # noqa: E501 + # from C:\Users\runneradmin\AppData\Local\Temp\pytest-of-runneradmin\pytest-0\A7\packages\arduino\hardware\mbed\1.1.4\cores\arduino/Arduino.h:32, # noqa: E501 + # from C:\Users\RUNNER~1\AppData\Local\Temp\arduino-sketch-739B2B6DD21EB014317DA2A46062811B\sketch\magic_wand.ino.cpp:1: # noqa: E501 + # [error]c:\users\runneradmin\appdata\local\temp\pytest-of-runneradmin\pytest-0\a7\packages\arduino\tools\arm-none-eabi-gcc\7-2017q4\arm-none-eabi\include\c++\7.2.1\new:39:10: fatal error: bits/c++config.h: No such file or directory # noqa: E501 # # due to the above on Windows we cut the tmp path straight to /tmp/xxxxxxxx if platform.system() == "Windows": @@ -96,9 +96,7 @@ def _run(cmd_string): cli_full_line = "{} {}".format(cli_path, cmd_string) run_context = Context() with run_context.cd(working_dir): - return run_context.run( - cli_full_line, echo=False, hide=True, warn=True, env=env - ) + return run_context.run(cli_full_line, echo=False, hide=True, warn=True, env=env) return _run @@ -125,9 +123,7 @@ def daemon_runner(pytestconfig, data_dir, downloads_dir, working_dir): run_context.cd(working_dir) # Local Class is the implementation of a Runner abstract class runner = Local(run_context) - runner.run( - cli_full_line, echo=False, hide=True, warn=True, env=env, asynchronous=True - ) + runner.run(cli_full_line, echo=False, hide=True, warn=True, env=env, asynchronous=True) # we block here until the test function using this fixture has returned yield runner diff --git a/test/test_board.py b/test/test_board.py index c26d403cd4f..abbe16468fc 100644 --- a/test/test_board.py +++ b/test/test_board.py @@ -39,6 +39,7 @@ def test_board_listall(run_command): assert result.ok assert ["Board", "Name", "FQBN"] == result.stdout.splitlines()[0].strip().split() + def test_board_details(run_command): gold_board_details = """ { @@ -391,7 +392,7 @@ def test_board_details(run_command): } ] } -""" +""" # noqa: E501 result = run_command("core update-index") assert result.ok # Download samd core pinned to 1.8.6 diff --git a/test/test_compile.py b/test/test_compile.py index 6abbc3810f4..b2bef620faf 100644 --- a/test/test_compile.py +++ b/test/test_compile.py @@ -70,9 +70,7 @@ def test_compile_with_simple_sketch(run_command, data_dir, working_dir): "Compile {sketch} for {fqbn} started".format(sketch=sketch_path, fqbn=fqbn), "Compile {sketch} for {fqbn} successful".format(sketch=sketch_name, fqbn=fqbn), ] - assert is_message_sequence_in_json_log_traces( - expected_trace_sequence, json_log_lines - ) + assert is_message_sequence_in_json_log_traces(expected_trace_sequence, json_log_lines) # Test the --output-dir flag with absolute path target = os.path.join(data_dir, "test_dir") @@ -105,11 +103,7 @@ def test_output_flag_default_path(run_command, data_dir, working_dir): assert result.ok # Test the --output-dir flag defaulting to current working dir - result = run_command( - "compile -b {fqbn} {sketch_path} --output-dir test".format( - fqbn=fqbn, sketch_path=sketch_path - ) - ) + result = run_command("compile -b {fqbn} {sketch_path} --output-dir test".format(fqbn=fqbn, sketch_path=sketch_path)) assert result.ok target = os.path.join(working_dir, "test") assert os.path.exists(target) and os.path.isdir(target) @@ -138,9 +132,7 @@ def test_compile_with_sketch_with_symlink_selfloop(run_command, data_dir): os.symlink(loop_file_path, loop_file_path) # Build sketch for arduino:avr:uno - result = run_command( - "compile -b {fqbn} {sketch_path}".format(fqbn=fqbn, sketch_path=sketch_path) - ) + result = run_command("compile -b {fqbn} {sketch_path}".format(fqbn=fqbn, sketch_path=sketch_path)) # The assertion is a bit relaxed in this case because win behaves differently from macOs and linux # returning a different error detailed message assert "Error during sketch processing" in result.stderr @@ -162,9 +154,7 @@ def test_compile_with_sketch_with_symlink_selfloop(run_command, data_dir): os.symlink(loop_dir_path, loop_dir_symlink_path) # Build sketch for arduino:avr:uno - result = run_command( - "compile -b {fqbn} {sketch_path}".format(fqbn=fqbn, sketch_path=sketch_path) - ) + result = run_command("compile -b {fqbn} {sketch_path}".format(fqbn=fqbn, sketch_path=sketch_path)) # The assertion is a bit relaxed also in this case because macOS behaves differently from win and linux: # the cli does not follow recursively the symlink til breaking assert "Error during sketch processing" in result.stderr @@ -185,7 +175,7 @@ def test_compile_and_upload_combo(run_command, data_dir, detected_boards): # Create a test sketch sketch_name = "CompileAndUploadIntegrationTest" sketch_path = os.path.join(data_dir, sketch_name) - sketch_main_file = os.path.join(sketch_path, sketch_name+".ino") + sketch_main_file = os.path.join(sketch_path, sketch_name + ".ino") result = run_command("sketch new {}".format(sketch_path)) assert result.ok assert "Sketch created in: {}".format(sketch_path) in result.stdout @@ -194,17 +184,12 @@ def test_compile_and_upload_combo(run_command, data_dir, detected_boards): for board in detected_boards: log_file_name = "{fqbn}-compile.log".format(fqbn=board.fqbn.replace(":", "-")) log_file_path = os.path.join(data_dir, log_file_name) - command_log_flags = "--log-format json --log-file {} --log-level trace".format( - log_file_path - ) + command_log_flags = "--log-format json --log-file {} --log-level trace".format(log_file_path) def run_test(s): result = run_command( "compile -b {fqbn} --upload -p {address} {sketch_path} {log_flags}".format( - fqbn=board.fqbn, - address=board.address, - sketch_path=s, - log_flags=command_log_flags, + fqbn=board.fqbn, address=board.address, sketch_path=s, log_flags=command_log_flags, ) ) assert result.ok @@ -213,22 +198,12 @@ def run_test(s): log_json = open(log_file_path, "r") json_log_lines = log_json.readlines() expected_trace_sequence = [ - "Compile {sketch} for {fqbn} started".format( - sketch=sketch_path, fqbn=board.fqbn - ), - "Compile {sketch} for {fqbn} successful".format( - sketch=sketch_name, fqbn=board.fqbn - ), - "Upload {sketch} on {fqbn} started".format( - sketch=sketch_path, fqbn=board.fqbn - ), - "Upload {sketch} on {fqbn} successful".format( - sketch=sketch_name, fqbn=board.fqbn - ), + "Compile {sketch} for {fqbn} started".format(sketch=sketch_path, fqbn=board.fqbn), + "Compile {sketch} for {fqbn} successful".format(sketch=sketch_name, fqbn=board.fqbn), + "Upload {sketch} on {fqbn} started".format(sketch=sketch_path, fqbn=board.fqbn), + "Upload {sketch} on {fqbn} successful".format(sketch=sketch_name, fqbn=board.fqbn), ] - assert is_message_sequence_in_json_log_traces( - expected_trace_sequence, json_log_lines - ) + assert is_message_sequence_in_json_log_traces(expected_trace_sequence, json_log_lines) run_test(sketch_path) run_test(sketch_main_file) @@ -267,11 +242,7 @@ def test_compile_blacklisted_sketchname(run_command, data_dir): assert "Sketch created in: {}".format(sketch_path) in result.stdout # Build sketch for arduino:avr:uno - log_file_name = "compile.log" - log_file_path = os.path.join(data_dir, log_file_name) - result = run_command( - "compile -b {fqbn} {sketch_path}".format(fqbn=fqbn, sketch_path=sketch_path) - ) + result = run_command("compile -b {fqbn} {sketch_path}".format(fqbn=fqbn, sketch_path=sketch_path)) assert result.ok @@ -290,27 +261,44 @@ def test_compile_without_precompiled_libraries(run_command, data_dir): # Install pre-release version of Arduino_TensorFlowLite (will be officially released # via lib manager after https://github.com/arduino/arduino-builder/issues/353 is in) import zipfile - with zipfile.ZipFile("test/testdata/Arduino_TensorFlowLite.zip", 'r') as zip_ref: + + with zipfile.ZipFile("test/testdata/Arduino_TensorFlowLite.zip", "r") as zip_ref: zip_ref.extractall("{}/libraries/".format(data_dir)) result = run_command("lib install Arduino_LSM9DS1@1.1.0") assert result.ok - result = run_command("compile -b arduino:mbed:nano33ble {}/libraries/Arduino_TensorFlowLite/examples/magic_wand/".format(data_dir)) + result = run_command( + "compile -b arduino:mbed:nano33ble {}/libraries/Arduino_TensorFlowLite/examples/magic_wand/".format(data_dir) + ) assert result.ok - result = run_command("compile -b adafruit:samd:adafruit_feather_m4 {}/libraries/Arduino_TensorFlowLite/examples/magic_wand/".format(data_dir)) + result = run_command( + "compile -b adafruit:samd:adafruit_feather_m4 {}/libraries/Arduino_TensorFlowLite/examples/magic_wand/".format( + data_dir + ) + ) assert result.ok # Non-precompiled version of Arduino_TensorflowLite result = run_command("lib install Arduino_TensorflowLite@1.15.0-ALPHA") assert result.ok - result = run_command("compile -b arduino:mbed:nano33ble {}/libraries/Arduino_TensorFlowLite/examples/magic_wand/".format(data_dir)) + result = run_command( + "compile -b arduino:mbed:nano33ble {}/libraries/Arduino_TensorFlowLite/examples/magic_wand/".format(data_dir) + ) assert result.ok - result = run_command("compile -b adafruit:samd:adafruit_feather_m4 {}/libraries/Arduino_TensorFlowLite/examples/magic_wand/".format(data_dir)) + result = run_command( + "compile -b adafruit:samd:adafruit_feather_m4 {}/libraries/Arduino_TensorFlowLite/examples/magic_wand/".format( + data_dir + ) + ) assert result.ok # Bosch sensor library - result = run_command("lib install \"BSEC Software Library@1.5.1474\"") + result = run_command('lib install "BSEC Software Library@1.5.1474"') assert result.ok - result = run_command("compile -b arduino:samd:mkr1000 {}/libraries/BSEC_Software_Library/examples/basic/".format(data_dir)) + result = run_command( + "compile -b arduino:samd:mkr1000 {}/libraries/BSEC_Software_Library/examples/basic/".format(data_dir) + ) assert result.ok - result = run_command("compile -b arduino:mbed:nano33ble {}/libraries/BSEC_Software_Library/examples/basic/".format(data_dir)) + result = run_command( + "compile -b arduino:mbed:nano33ble {}/libraries/BSEC_Software_Library/examples/basic/".format(data_dir) + ) assert result.ok diff --git a/test/test_completion.py b/test/test_completion.py index 3f6bc303534..120110ec7c4 100644 --- a/test/test_completion.py +++ b/test/test_completion.py @@ -13,7 +13,6 @@ # software without disclosing the source code of your own applications. To purchase # a commercial license, send an email to license@arduino.cc. -import pytest def test_completion_no_args(run_command): result = run_command("completion") @@ -21,6 +20,7 @@ def test_completion_no_args(run_command): assert "Error: accepts 1 arg(s), received 0" in result.stderr assert result.stdout == "" + def test_completion_bash(run_command): result = run_command("completion bash") assert result.ok @@ -28,6 +28,7 @@ def test_completion_bash(run_command): assert "_arduino-cli_root_command()" in result.stdout assert "__start_arduino-cli()" in result.stdout + def test_completion_zsh(run_command): result = run_command("completion zsh") assert result.ok @@ -35,6 +36,7 @@ def test_completion_zsh(run_command): assert "#compdef _arduino-cli arduino-cli" in result.stdout assert "function _arduino-cli" in result.stdout + def test_completion_fish(run_command): result = run_command("completion fish") assert result.ok @@ -42,22 +44,25 @@ def test_completion_fish(run_command): assert "# fish completion for arduino-cli" in result.stdout assert "function __arduino-cli_perform_completion" in result.stdout + def test_completion_bash_no_desc(run_command): result = run_command("completion bash --no-descriptions") assert not result.ok assert result.stdout == "" assert "Error: command description is not supported by bash" in result.stderr + def test_completion_zsh_no_desc(run_command): result = run_command("completion zsh --no-descriptions") assert not result.ok assert result.stdout == "" assert "Error: command description is not supported by zsh" in result.stderr + def test_completion_fish_no_desc(run_command): result = run_command("completion fish --no-descriptions") assert result.ok assert result.stderr == "" assert "# fish completion for arduino-cli" in result.stdout assert "function __arduino-cli_perform_completion" in result.stdout - assert "__completeNoDesc" in result.stdout \ No newline at end of file + assert "__completeNoDesc" in result.stdout diff --git a/test/test_core.py b/test/test_core.py index 7b0178bab02..0b69ec68872 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -17,8 +17,6 @@ import pytest import simplejson as json -from .common import running_on_ci - def test_core_search(run_command): url = "https://raw.githubusercontent.com/arduino/arduino-cli/master/test/testdata/test_index.json" @@ -32,16 +30,12 @@ def test_core_search(run_command): data = json.loads(result.stdout) assert 0 < len(data) # additional URL - result = run_command( - "core search test_core --format json --additional-urls={}".format(url) - ) + result = run_command("core search test_core --format json --additional-urls={}".format(url)) assert result.ok data = json.loads(result.stdout) assert 1 == len(data) # show all versions - result = run_command( - "core search test_core --all --format json --additional-urls={}".format(url) - ) + result = run_command("core search test_core --all --format json --additional-urls={}".format(url)) assert result.ok data = json.loads(result.stdout) assert 2 == len(data) @@ -106,8 +100,7 @@ def test_core_updateindex_invalid_url(run_command): @pytest.mark.skipif( - platform.system() == "Windows", - reason="core fails with fatal error: bits/c++config.h: No such file or directory", + platform.system() == "Windows", reason="core fails with fatal error: bits/c++config.h: No such file or directory", ) def test_core_install_esp32(run_command, data_dir): # update index @@ -121,9 +114,7 @@ def test_core_install_esp32(run_command, data_dir): assert run_command("compile -b esp32:esp32:esp32 {}".format(sketch_path)) # prevent regressions for https://github.com/arduino/arduino-cli/issues/163 assert os.path.exists( - os.path.join( - sketch_path, "build/esp32.esp32.esp32/test_core_install_esp32.ino.partitions.bin" - ) + os.path.join(sketch_path, "build/esp32.esp32.esp32/test_core_install_esp32.ino.partitions.bin",) ) diff --git a/test/test_daemon.py b/test/test_daemon.py index 121dfbfe04b..6397d04282b 100644 --- a/test/test_daemon.py +++ b/test/test_daemon.py @@ -31,14 +31,14 @@ def test_telemetry_prometheus_endpoint(daemon_runner, data_dir): inventory_file = os.path.join(data_dir, "inventory.yaml") while not os.path.exists(inventory_file): time.sleep(1) - with open(inventory_file, 'r') as stream: + with open(inventory_file, "r") as stream: inventory = yaml.safe_load(stream) # Check if :9090/metrics endpoint is alive, # telemetry is enabled by default in daemon mode s = requests.Session() retries = Retry(total=3, backoff_factor=1, status_forcelist=[500, 502, 503, 504]) - s.mount('http://', HTTPAdapter(max_retries=retries)) + s.mount("http://", HTTPAdapter(max_retries=retries)) metrics = s.get("http://localhost:9090/metrics").text family = next(text_string_to_metric_families(metrics)) sample = family.samples[0] diff --git a/test/test_lib.py b/test/test_lib.py index 933a90c6a36..457b2eb883f 100644 --- a/test/test_lib.py +++ b/test/test_lib.py @@ -63,18 +63,13 @@ def test_install(run_command): # Test failing-install of library with wrong dependency # (https://github.com/arduino/arduino-cli/issues/534) result = run_command("lib install MD_Parola@3.2.0") - assert ( - "Error resolving dependencies for MD_Parola@3.2.0: dependency 'MD_MAX72xx' is not available" - in result.stderr - ) + assert "Error resolving dependencies for MD_Parola@3.2.0: dependency 'MD_MAX72xx' is not available" in result.stderr + def test_update_index(run_command): result = run_command("lib update-index") assert result.ok - assert ( - "Updating index: library_index.json downloaded" - == result.stdout.splitlines()[-1].strip() - ) + assert "Updating index: library_index.json downloaded" == result.stdout.splitlines()[-1].strip() def test_uninstall(run_command): @@ -84,6 +79,7 @@ def test_uninstall(run_command): result = run_command("lib uninstall {}".format(" ".join(libs))) assert result.ok + def test_uninstall_spaces(run_command): key = '"LiquidCrystal I2C"' assert run_command("lib install {}".format(key)) @@ -92,6 +88,7 @@ def test_uninstall_spaces(run_command): assert result.ok assert len(json.loads(result.stdout)) == 0 + def test_lib_ops_caseinsensitive(run_command): """ This test is supposed to (un)install the following library, @@ -108,13 +105,14 @@ def test_lib_ops_caseinsensitive(run_command): Types: Contributed Versions: [1.0.0] """ - key = 'pcm' + key = "pcm" assert run_command("lib install {}".format(key)) assert run_command("lib uninstall {}".format(key)) result = run_command("lib list --format json") assert result.ok assert len(json.loads(result.stdout)) == 0 + def test_search(run_command): assert run_command("lib update-index") @@ -151,9 +149,7 @@ def test_search_paragraph(run_command): within the index file. """ assert run_command("lib update-index") - result = run_command( - 'lib search "A simple and efficient JSON library" --format json' - ) + result = run_command('lib search "A simple and efficient JSON library" --format json') assert result.ok libs_json = json.loads(result.stdout) assert 1 == len(libs_json.get("libraries")) diff --git a/test/test_main.py b/test/test_main.py index 2ff2d4839a7..80f8e39072a 100644 --- a/test/test_main.py +++ b/test/test_main.py @@ -86,6 +86,6 @@ def test_inventory_creation(run_command, data_dir): # parse inventory file inventory_file = os.path.join(data_dir, "inventory.yaml") - with open(inventory_file, 'r') as stream: + with open(inventory_file, "r") as stream: inventory = yaml.safe_load(stream) assert "installation" in inventory diff --git a/test/test_sketch.py b/test/test_sketch.py index 39a9f56f546..37c7605ddf4 100644 --- a/test/test_sketch.py +++ b/test/test_sketch.py @@ -20,8 +20,10 @@ from test.common import running_on_ci -@pytest.mark.skipif(running_on_ci() and platform.system() == "Windows", - reason="Test disabled on Github Actions Win VM until tmpdir inconsistent behavior bug is fixed") +@pytest.mark.skipif( + running_on_ci() and platform.system() == "Windows", + reason="Test disabled on Github Actions Win VM until tmpdir inconsistent behavior bug is fixed", +) def test_sketch_new(run_command, working_dir): # Create a test sketch in current directory current_path = working_dir diff --git a/test/test_upload.py b/test/test_upload.py index bb44b8dbe58..439bd98d084 100644 --- a/test/test_upload.py +++ b/test/test_upload.py @@ -33,17 +33,9 @@ def test_upload(run_command, data_dir, detected_boards): sketch_path = os.path.join(data_dir, "foo") assert run_command("sketch new {}".format(sketch_path)) # Build sketch - assert run_command( - "compile -b {fqbn} {sketch_path}".format( - fqbn=board.fqbn, sketch_path=sketch_path - ) - ) + assert run_command("compile -b {fqbn} {sketch_path}".format(fqbn=board.fqbn, sketch_path=sketch_path)) # Upload without port must fail - result = run_command( - "upload -b {fqbn} {sketch_path}".format( - sketch_path=sketch_path, fqbn=board.fqbn, port=board.address - ) - ) + result = run_command("upload -b {fqbn} {sketch_path}".format(sketch_path=sketch_path, fqbn=board.fqbn)) assert result.failed # Upload assert run_command(