From 513df67f58ece9f7421f5cf06d4d69ff965dfbec Mon Sep 17 00:00:00 2001 From: Sorin Sbarnea Date: Mon, 20 May 2024 20:36:56 +0100 Subject: [PATCH] Complete coverage --- .github/workflows/tox.yml | 2 +- .vscode/extensions.json | 16 +-- .vscode/settings.json | 22 +-- pyproject.toml | 257 ++++++++++++++++++++++++++++++++-- src/ansible_compat/runtime.py | 4 +- test/test_types.py | 9 ++ test/test_version.py | 13 ++ 7 files changed, 288 insertions(+), 35 deletions(-) create mode 100644 test/test_types.py create mode 100644 test/test_version.py diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index 97414ae4..4bbe727e 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -48,7 +48,7 @@ jobs: matrix: ${{ fromJson(needs.prepare.outputs.matrix) }} env: FORCE_COLOR: 1 - PYTEST_REQPASS: 106 + PYTEST_REQPASS: 108 steps: - uses: actions/checkout@v4 with: diff --git a/.vscode/extensions.json b/.vscode/extensions.json index aa1e5371..ca0ca528 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,19 +1,19 @@ { "recommendations": [ - "Tyriar.sort-lines", "charliermarsh.ruff", "esbenp.prettier-vscode", - "hbenl.vscode-test-explorer", - "ms-python.isort", + "markis.code-coverage", + "ms-python.black-formatter", + "ms-python.debugpy", + "ms-python.mypy-type-checker", + "ms-python.pylint", "ms-python.python", - "ms-python.vscode-pylance", - "ms-vscode.live-server", "redhat.ansible", "redhat.vscode-yaml", - "ryanluker.vscode-coverage-gutters", "shardulm94.trailing-spaces", + "streetsidesoftware.code-spell-checker", "tamasfe.even-better-toml", - "timonwong.shellcheck", "znck.grammarly" - ] + ], + "unwantedRecommendations": ["ryanluker.vscode-coverage-gutters"] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 990033df..a4369f34 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,13 +1,17 @@ { + "[jsonc]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, "[markdown]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, "[python]": { "editor.codeActionsOnSave": { "source.fixAll": "explicit", - "source.fixAll.ruff": "never", - "source.organizeImports": "never" - } + "source.organizeImports": "explicit" + }, + "editor.defaultFormatter": "ms-python.black-formatter", + "editor.formatOnSave": true }, "editor.formatOnSave": true, "evenBetterToml.formatter.alignComments": false, @@ -24,17 +28,15 @@ "grammarly.files.include": ["**/*.txt", "**/*.md"], "grammarly.hideUnavailablePremiumAlerts": true, "grammarly.showExamples": true, + "markiscodecoverage.searchCriteria": "coverage.lcov", + "mypy-type-checker.importStrategy": "fromEnvironment", + "mypy-type-checker.preferDaemon": true, + "mypy-type-checker.reportingScope": "workspace", "python.analysis.exclude": ["build"], - "python.formatting.provider": "black", - "python.linting.flake8Args": ["--ignore=E501,W503"], - "python.linting.flake8Enabled": false, - "python.linting.mypyCategorySeverity.error": "Warning", - "python.linting.mypyEnabled": true, - "python.linting.pylintEnabled": true, "python.terminal.activateEnvironment": true, + "python.testing.pytestArgs": ["tests"], "python.testing.pytestEnabled": true, "python.testing.unittestEnabled": false, - "sortLines.filterBlankLines": true, "yaml.completion": true, "yaml.customTags": ["!encrypted/pkcs1-oaep scalar", "!vault scalar"], "yaml.format.enable": false, diff --git a/pyproject.toml b/pyproject.toml index d7216c2c..5119f43d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [build-system] requires = [ "setuptools >= 65.3.0", # required by pyproject+setuptools_scm integration and editable installs - "setuptools_scm[toml] >= 7.0.5" # required for "no-local-version" scheme + "setuptools_scm[toml] >= 7.0.5", # required for "no-local-version" scheme ] build-backend = "setuptools.build_meta" @@ -12,9 +12,9 @@ dynamic = ["version", "dependencies", "optional-dependencies"] name = "ansible-compat" description = "Ansible compatibility goodies" readme = "README.md" -authors = [{"name" = "Sorin Sbarnea", "email" = "ssbarnea@redhat.com"}] -maintainers = [{"name" = "Sorin Sbarnea", "email" = "ssbarnea@redhat.com"}] -license = {text = "MIT"} +authors = [{ "name" = "Sorin Sbarnea", "email" = "ssbarnea@redhat.com" }] +maintainers = [{ "name" = "Sorin Sbarnea", "email" = "ssbarnea@redhat.com" }] +license = { text = "MIT" } classifiers = [ "Development Status :: 5 - Production/Stable", "Environment :: Console", @@ -33,7 +33,7 @@ classifiers = [ "Topic :: Software Development :: Bug Tracking", "Topic :: Software Development :: Quality Assurance", "Topic :: Software Development :: Testing", - "Topic :: Utilities" + "Topic :: Utilities", ] keywords = ["ansible"] @@ -51,7 +51,6 @@ show_missing = true [tool.coverage.run] source = ["src"] -omit = ["src/ansible_compat/types.py"] # Do not use branch until bug is fixes: # https://github.com/nedbat/coveragepy/issues/605 branch = false @@ -78,6 +77,11 @@ exclude = "test/local-content" module = "ansible.*" ignore_missing_imports = true +[[tool.mypy.overrides]] +# generated by setuptools-scm, can be missing during linting +module = "ansible_compat._version" +ignore_errors = true + [tool.pylint.BASIC] good-names = [ "f", # filename @@ -87,23 +91,248 @@ good-names = [ "ns", # namespace "ex", "Run", - "_" + "_", ] [tool.pylint.IMPORTS] preferred-modules = ["unittest:pytest"] +[tool.pylint.MASTER] +# _version.py is generated by setuptools-scm. +ignore-paths = "^src/ansible_compat/_version.py" + [tool.pylint."MESSAGES CONTROL"] disable = [ + "unknown-option-value", + # https://gist.github.com/cidrblock/ec3412bacfeb34dbc2d334c1d53bef83 + "C0103", # invalid-name / ruff N815 + "C0105", # typevar-name-incorrect-variance / ruff PLC0105 + "C0112", # empty-docstring / ruff D419 + "C0113", # unneeded-not / ruff SIM208 + "C0114", # missing-module-docstring / ruff D100 + "C0115", # missing-class-docstring / ruff D101 + "C0116", # missing-function-docstring / ruff D103 + "C0121", # singleton-comparison / ruff PLC0121 + "C0123", # unidiomatic-typecheck / ruff E721 + "C0131", # typevar-double-variance / ruff PLC0131 + "C0132", # typevar-name-mismatch / ruff PLC0132 + "C0198", # bad-docstring-quotes / ruff Q002 + "C0199", # docstring-first-line-empty / ruff D210 + "C0201", # consider-iterating-dictionary / ruff SIM118 + "C0202", # bad-classmethod-argument / ruff PLC0202 + "C0205", # single-string-used-for-slots / ruff PLC0205 + "C0208", # use-sequence-for-iteration / ruff PLC0208 + "C0301", # line-too-long / ruff E501 + "C0303", # trailing-whitespace / ruff W291 + "C0304", # missing-final-newline / ruff W292 + "C0321", # multiple-statements / ruff PLC0321 + "C0410", # multiple-imports / ruff E401 + "C0411", # wrong-import-order / ruff I001 + "C0412", # ungrouped-imports / ruff I001 + "C0413", # wrong-import-position / ruff E402 + "C0414", # useless-import-alias / ruff PLC0414 + "C0415", # import-outside-toplevel / ruff PLC0415 + "C0501", # consider-using-any-or-all / ruff PLC0501 + "C1901", # compare-to-empty-string / ruff PLC1901 + "C2201", # misplaced-comparison-constant / ruff SIM300 + "C2401", # non-ascii-name / ruff PLC2401 + "C2403", # non-ascii-module-import / ruff PLC2403 + "C2701", # import-private-name / ruff PLC2701 + "C2801", # unnecessary-dunder-call / ruff PLC2801 + "C3001", # unnecessary-lambda-assignment / ruff E731 + "C3002", # unnecessary-direct-lambda-call / ruff PLC3002 + "E0001", # syntax-error / ruff E999 + "E0100", # init-is-generator / ruff PLE0100 + "E0101", # return-in-init / ruff PLE0101 + "E0102", # function-redefined / ruff F811 + "E0103", # not-in-loop / ruff PLE0103 + "E0104", # return-outside-function / ruff F706 + "E0105", # yield-outside-function / ruff F704 + "E0107", # nonexistent-operator / ruff B002 + "E0112", # too-many-star-expressions / ruff F622 + "E0115", # nonlocal-and-global / ruff PLE0115 + "E0116", # continue-in-finally / ruff PLE0116 + "E0117", # nonlocal-without-binding / ruff PLE0117 + "E0118", # used-prior-global-declaration / ruff PLE0118 + "E0211", # no-method-argument / ruff N805 + "E0213", # no-self-argument / ruff N805 + "E0237", # assigning-non-slot / ruff PLE0237 + "E0241", # duplicate-bases / ruff PLE0241 + "E0302", # unexpected-special-method-signature / ruff PLE0302 + "E0303", # invalid-length-returned / ruff PLE0303 + "E0304", # invalid-bool-returned / ruff PLE0304 + "E0305", # invalid-index-returned / ruff PLE0305 + "E0308", # invalid-bytes-returned / ruff PLE0308 + "E0309", # invalid-hash-returned / ruff PLE0309 + "E0402", # relative-beyond-top-level / ruff TID252 + "E0602", # undefined-variable / ruff F821 + "E0603", # undefined-all-variable / ruff F822 + "E0604", # invalid-all-object / ruff PLE0604 + "E0605", # invalid-all-format / ruff PLE0605 + "E0643", # potential-index-error / ruff PLE0643 + "E0704", # misplaced-bare-raise / ruff PLE0704 + "E0711", # notimplemented-raised / ruff F901 + "E1132", # repeated-keyword / ruff PLE1132 + "E1142", # await-outside-async / ruff PLE1142 + "E1205", # logging-too-many-args / ruff PLE1205 + "E1206", # logging-too-few-args / ruff PLE1206 + "E1300", # bad-format-character / ruff PLE1300 + "E1301", # truncated-format-string / ruff F501 + "E1302", # mixed-format-string / ruff F506 + "E1303", # format-needs-mapping / ruff F502 + "E1304", # missing-format-string-key / ruff F524 + "E1305", # too-many-format-args / ruff F522 + "E1306", # too-few-format-args / ruff F524 + "E1307", # bad-string-format-type / ruff PLE1307 + "E1310", # bad-str-strip-call / ruff PLE1310 + "E1519", # singledispatch-method / ruff PLE1519 + "E1520", # singledispatchmethod-function / ruff PLE5120 + "E1700", # yield-inside-async-function / ruff PLE1700 + "E2502", # bidirectional-unicode / ruff PLE2502 + "E2510", # invalid-character-backspace / ruff PLE2510 + "E2512", # invalid-character-sub / ruff PLE2512 + "E2513", # invalid-character-esc / ruff PLE2513 + "E2514", # invalid-character-nul / ruff PLE2514 + "E2515", # invalid-character-zero-width-space / ruff PLE2515 + "E4703", # modified-iterating-set / ruff PLE4703 + "R0123", # literal-comparison / ruff F632 + "R0124", # comparison-with-itself / ruff PLR0124 + "R0133", # comparison-of-constants / ruff PLR0133 + "R0202", # no-classmethod-decorator / ruff PLR0202 + "R0203", # no-staticmethod-decorator / ruff PLR0203 + "R0205", # useless-object-inheritance / ruff UP004 + "R0206", # property-with-parameters / ruff PLR0206 + "R0904", # too-many-public-methods / ruff PLR0904 + "R0911", # too-many-return-statements / ruff PLR0911 + "R0912", # too-many-branches / ruff PLR0912 + "R0913", # too-many-arguments / ruff PLR0913 + "R0914", # too-many-locals / ruff PLR0914 + "R0915", # too-many-statements / ruff PLR0915 + "R0916", # too-many-boolean-expressions / ruff PLR0916 + "R1260", # too-complex / ruff C901 + "R1701", # consider-merging-isinstance / ruff PLR1701 + "R1702", # too-many-nested-blocks / ruff PLR1702 + "R1703", # simplifiable-if-statement / ruff SIM108 + "R1704", # redefined-argument-from-local / ruff PLR1704 + "R1705", # no-else-return / ruff RET505 + "R1706", # consider-using-ternary / ruff PLR1706 + "R1707", # trailing-comma-tuple / ruff COM818 + "R1710", # inconsistent-return-statements / ruff PLR1710 + "R1711", # useless-return / ruff PLR1711 + "R1714", # consider-using-in / ruff PLR1714 + "R1715", # consider-using-get / ruff SIM401 + "R1717", # consider-using-dict-comprehension / ruff C402 + "R1718", # consider-using-set-comprehension / ruff C401 + "R1719", # simplifiable-if-expression / ruff PLR1719 + "R1720", # no-else-raise / ruff RET506 + "R1721", # unnecessary-comprehension / ruff C416 + "R1722", # consider-using-sys-exit / ruff PLR1722 + "R1723", # no-else-break / ruff RET508 + "R1724", # no-else-continue / ruff RET507 + "R1725", # super-with-arguments / ruff UP008 + "R1728", # consider-using-generator / ruff C417 + "R1729", # use-a-generator / ruff C419 + "R1730", # consider-using-min-builtin / ruff PLR1730 + "R1731", # consider-using-max-builtin / ruff PLR1730 + "R1732", # consider-using-with / ruff SIM115 + "R1733", # unnecessary-dict-index-lookup / ruff PLR1733 + "R1734", # use-list-literal / ruff C405 + "R1735", # use-dict-literal / ruff C406 + "R1736", # unnecessary-list-index-lookup / ruff PLR1736 + "R2004", # magic-value-comparison / ruff PLR2004 + "R2044", # empty-comment / ruff PLR2044 + "R5501", # else-if-used / ruff PLR5501 + "R6002", # consider-using-alias / ruff UP006 + "R6003", # consider-alternative-union-syntax / ruff UP007 + "R6104", # consider-using-augmented-assign / ruff PLR6104 + "R6201", # use-set-for-membership / ruff PLR6201 + "R6301", # no-self-use / ruff PLR6301 + "W0102", # dangerous-default-value / ruff B006 + "W0104", # pointless-statement / ruff B018 + "W0106", # expression-not-assigned / ruff B018 + "W0107", # unnecessary-pass / ruff PIE790 + "W0108", # unnecessary-lambda / ruff PLW0108 + "W0109", # duplicate-key / ruff F601 + "W0120", # useless-else-on-loop / ruff PLW0120 + "W0122", # exec-used / ruff S102 + "W0123", # eval-used / ruff PGH001 + "W0127", # self-assigning-variable / ruff PLW0127 + "W0129", # assert-on-string-literal / ruff PLW0129 + "W0130", # duplicate-value / ruff B033 + "W0131", # named-expr-without-context / ruff PLW0131 + "W0133", # pointless-exception-statement / ruff PLW0133 + "W0150", # lost-exception / ruff B012 + "W0160", # consider-ternary-expression / ruff SIM108 + "W0177", # nan-comparison / ruff PLW0117 + "W0199", # assert-on-tuple / ruff F631 + "W0211", # bad-staticmethod-argument / ruff PLW0211 + "W0212", # protected-access / ruff SLF001 + "W0245", # super-without-brackets / ruff PLW0245 + "W0301", # unnecessary-semicolon / ruff E703 + "W0401", # wildcard-import / ruff F403 + "W0404", # reimported / ruff F811 + "W0406", # import-self / ruff PLW0406 + "W0410", # misplaced-future / ruff F404 + "W0511", # fixme / ruff PLW0511 + "W0602", # global-variable-not-assigned / ruff PLW0602 + "W0603", # global-statement / ruff PLW0603 + "W0604", # global-at-module-level / ruff PLW0604 + "W0611", # unused-import / ruff F401 + "W0612", # unused-variable / ruff F841 + "W0613", # unused-argument / ruff ARG001 + "W0622", # redefined-builtin / ruff A001 + "W0640", # cell-var-from-loop / ruff B023 + "W0702", # bare-except / ruff E722 + "W0705", # duplicate-except / ruff B014 + "W0706", # try-except-raise / ruff TRY302 + "W0707", # raise-missing-from / ruff TRY200 + "W0711", # binary-op-exception / ruff PLW0711 + "W0718", # broad-exception-caught / ruff PLW0718 + "W0719", # broad-exception-raised / ruff TRY002 + "W1113", # keyword-arg-before-vararg / ruff B026 + "W1201", # logging-not-lazy / ruff G + "W1202", # logging-format-interpolation / ruff G + "W1203", # logging-fstring-interpolation / ruff G + "W1300", # bad-format-string-key / ruff PLW1300 + "W1301", # unused-format-string-key / ruff F504 + "W1302", # bad-format-string / ruff PLW1302 + "W1303", # missing-format-argument-key / ruff F524 + "W1304", # unused-format-string-argument / ruff F507 + "W1305", # format-combined-specification / ruff F525 + "W1308", # duplicate-string-formatting-argument / ruff PLW1308 + "W1309", # f-string-without-interpolation / ruff F541 + "W1310", # format-string-without-interpolation / ruff F541 + "W1401", # anomalous-backslash-in-string / ruff W605 + "W1404", # implicit-str-concat / ruff ISC001 + "W1405", # inconsistent-quotes / ruff Q000 + "W1406", # redundant-u-string-prefix / ruff UP025 + "W1501", # bad-open-mode / ruff PLW1501 + "W1508", # invalid-envvar-default / ruff PLW1508 + "W1509", # subprocess-popen-preexec-fn / ruff PLW1509 + "W1510", # subprocess-run-check / ruff PLW1510 + "W1514", # unspecified-encoding / ruff PLW1514 + "W1515", # forgotten-debug-statement / ruff T100 + "W1518", # method-cache-max-size-none / ruff B019 + "W1641", # eq-without-hash / ruff PLW1641 + "W2101", # useless-with-lock / ruff PLW2101 + "W2402", # non-ascii-file-name / ruff N999 + "W2901", # redefined-loop-name / ruff PLW2901 + "W3201", # bad-dunder-name / ruff PLW3201 + "W3301", # nested-min-max / ruff PLW3301 + "duplicate-code", + "fixme", + "too-few-public-methods", + "unsubscriptable-object", # On purpose disabled as we rely on black "line-too-long", + "protected-access", # covered by ruff SLF001 # local imports do not work well with pre-commit hook "import-error", # already covered by ruff which is faster "too-many-arguments", # PLR0913 "raise-missing-from", # Temporary disable duplicate detection we remove old code from prerun - "duplicate-code" + "duplicate-code", ] [tool.pytest.ini_options] @@ -112,7 +341,7 @@ filterwarnings = [ "error", # py312 ansible-core # https://github.com/ansible/ansible/issues/81906 - "ignore:'importlib.abc.TraversableResources' is deprecated and slated for removal in Python 3.14:DeprecationWarning" + "ignore:'importlib.abc.TraversableResources' is deprecated and slated for removal in Python 3.14:DeprecationWarning", ] testpaths = ["test"] @@ -132,7 +361,7 @@ lint.ignore = [ "PLR0912", # Bug https://github.com/charliermarsh/ruff/issues/4244 "PLR0913", # Bug https://github.com/charliermarsh/ruff/issues/4244 "RUF012", - "PERF203" + "PERF203", ] [tool.ruff.lint.flake8-pytest-style] @@ -149,9 +378,9 @@ known-third-party = ["packaging"] convention = "pep257" [tool.setuptools.dynamic] -dependencies = {file = [".config/requirements.in"]} -optional-dependencies.docs = {file = [".config/requirements-docs.in"]} -optional-dependencies.test = {file = [".config/requirements-test.in"]} +dependencies = { file = [".config/requirements.in"] } +optional-dependencies.docs = { file = [".config/requirements-docs.in"] } +optional-dependencies.test = { file = [".config/requirements-test.in"] } [tool.setuptools_scm] local_scheme = "no-local-version" @@ -165,5 +394,5 @@ git_describe_command = [ "--tags", "--long", "--match", - "v*.*" + "v*.*", ] diff --git a/src/ansible_compat/runtime.py b/src/ansible_compat/runtime.py index c3c6ebe9..3b2488aa 100644 --- a/src/ansible_compat/runtime.py +++ b/src/ansible_compat/runtime.py @@ -227,7 +227,7 @@ def warning( msg: str, *, formatted: bool = False, # noqa: ARG001 - ) -> None: + ) -> None: # pragma: no cover """Override ansible.utils.display.Display.warning to avoid printing warnings.""" warnings.warn( message=msg, @@ -274,7 +274,7 @@ def load_collections(self) -> None: proc = self.run(["ansible-galaxy", "collection", "list", "--format=json"]) if proc.returncode == RC_ANSIBLE_OPTIONS_ERROR and ( no_collections_msg in proc.stdout or no_collections_msg in proc.stderr - ): + ): # pragma: no cover _logger.debug("Ansible reported no installed collections at all.") return if proc.returncode != 0: diff --git a/test/test_types.py b/test/test_types.py new file mode 100644 index 00000000..6702b486 --- /dev/null +++ b/test/test_types.py @@ -0,0 +1,9 @@ +"""Tests for types module.""" + +import ansible_compat.types + + +def test_types() -> None: + """Tests that JSON types are exported.""" + assert ansible_compat.types.JSON + assert ansible_compat.types.JSON_ro diff --git a/test/test_version.py b/test/test_version.py new file mode 100644 index 00000000..e6f869db --- /dev/null +++ b/test/test_version.py @@ -0,0 +1,13 @@ +"""Tests for _version module.""" + + +def test_version_module() -> None: + """Tests that _version exports are present.""" + # import kept here to allow mypy/pylint to run when module is not installed + # and the generated _version.py is missing. + # pylint: disable=no-name-in-module,no-member + import ansible_compat._version # type: ignore[import-not-found] + + assert ansible_compat._version.__version__ + assert ansible_compat._version.__version_tuple__ + assert ansible_compat._version.version