diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 00000000..c6ece29f --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,18 @@ +name: pre-commit +on: + pull_request: + push: + branches: [main] +jobs: + pre-commit: + runs-on: ubuntu-latest + env: + SKIP: no-commit-to-branch + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: | + 3.9 + 3.x + - uses: pre-commit/action@v3.0.0 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..67fc4d6c --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,16 @@ +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v2.3.0 + hooks: + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace +- repo: https://github.com/astral-sh/ruff-pre-commit + # Ruff version. + rev: v0.6.0 + hooks: + # Run the linter. + - id: ruff + args: [ --fix ] + # Run the formatter. + - id: ruff-format diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b63672cc..d0fd2751 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -25,9 +25,9 @@ Please don't include any private/sensitive information in your issue! ## Tools we use -- Python 3.6 -- [pylint](https://www.pylint.org/) -- [black](https://github.com/psf/black) +- Python >= 3.9 +- [pre-commit](https://pre-commit.com/) +- [ruff](https://docs.astral.sh/ruff/) - [tox](https://tox.readthedocs.io/en/latest/) - You may need to use [virtualenv](https://virtualenv.pypa.io/en/latest/) to support Python 3.6 @@ -65,10 +65,12 @@ tox -e coverage ## Coding conventions -- Use [black](https://github.com/psf/black) code formatter. If you have tox - installed, run `tox -e black` to see what changes will be made. You can use - `tox -e black-format` to update the code formatting prior to committing. -- Pass pylint +- Formatting and linting are incorporated using [ruff](https://docs.astral.sh/ruff/). +- If you use [pre-commit](https://pre-commit.com/) the checks will run automatically when you commit some changes +- If you prefer to run the ckecks with pre-commit, use `pre-commit run -a` to run the pre-commit checks for you. +- If you'd like to see what's happening with the checks you can run the [linter](https://docs.astral.sh/ruff/linter/) + and [formatter](https://docs.astral.sh/ruff/formatter/) separately with `ruff check --diff` and `ruff format --diff` +- Checks need to pass pylint - exceptions are possible, but you will need to make a good argument - Use spaces not tabs for indentation - This is open source software. Consider the people who will read your code, diff --git a/Makefile b/Makefile index 11ab79da..cbf87e67 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ podman: .PHONY: lint lint: tox - $(PYTHON) -m tox -e black,pylint + $(PYTHON) -m tox -e format,lint .PHONY: tests tests: tox diff --git a/contrib/cirrus/build_podman.sh b/contrib/cirrus/build_podman.sh index 9a217b0b..87218d71 100755 --- a/contrib/cirrus/build_podman.sh +++ b/contrib/cirrus/build_podman.sh @@ -7,4 +7,3 @@ systemctl stop podman.socket || : dnf erase podman -y dnf copr enable rhcontainerbot/podman-next -y dnf install podman -y - diff --git a/docs/source/_templates/apidoc/toc.rst_t b/docs/source/_templates/apidoc/toc.rst_t index f0877eeb..878540ce 100644 --- a/docs/source/_templates/apidoc/toc.rst_t +++ b/docs/source/_templates/apidoc/toc.rst_t @@ -5,4 +5,3 @@ {% for docname in docnames %} {{ docname }} {%- endfor %} - diff --git a/docs/source/conf.py b/docs/source/conf.py index caf916d3..e1e0845a 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -20,9 +20,9 @@ # -- Project information ----------------------------------------------------- -project = u'Podman Python SDK' -copyright = u'2021, Red Hat Inc' -author = u'Red Hat Inc' +project = 'Podman Python SDK' +copyright = '2021, Red Hat Inc' +author = 'Red Hat Inc' # The full version, including alpha/beta/rc tags version = '3.2.1.0' diff --git a/docs/source/index.rst b/docs/source/index.rst index d254b58d..fd729289 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -74,4 +74,4 @@ Indices and tables * :ref:`genindex` * :ref:`modindex` -* :ref:`search` \ No newline at end of file +* :ref:`search` diff --git a/podman/api/typing_extensions.py b/podman/api/typing_extensions.py index ff698f4c..ebddfa27 100644 --- a/podman/api/typing_extensions.py +++ b/podman/api/typing_extensions.py @@ -1604,6 +1604,7 @@ class GenProto(Protocol[T]): def meth(self) -> T: ... """ + __slots__ = () _is_protocol = True diff --git a/podman/domain/volumes.py b/podman/domain/volumes.py index 842ed7a4..6867d5c8 100644 --- a/podman/domain/volumes.py +++ b/podman/domain/volumes.py @@ -112,7 +112,8 @@ def list(self, *_, **kwargs) -> List[Volume]: return [self.prepare_model(i) for i in response.json()] def prune( - self, filters: Optional[Dict[str, str]] = None # pylint: disable=unused-argument + self, + filters: Optional[Dict[str, str]] = None, # pylint: disable=unused-argument ) -> Dict[Literal["VolumesDeleted", "SpaceReclaimed"], Any]: """Delete unused volumes. diff --git a/podman/tests/README.md b/podman/tests/README.md index ad5e01c0..ad35f5d8 100644 --- a/podman/tests/README.md +++ b/podman/tests/README.md @@ -7,4 +7,3 @@ ## Coverage Reporting Framework `coverage.py` see https://coverage.readthedocs.io/en/coverage-5.0.3/#quick-start - diff --git a/podman/tests/integration/base.py b/podman/tests/integration/base.py index d79711d9..3086730f 100644 --- a/podman/tests/integration/base.py +++ b/podman/tests/integration/base.py @@ -13,6 +13,7 @@ # under the License. # """Base integration test code""" + import logging import os import shutil diff --git a/podman/tests/integration/test_container_create.py b/podman/tests/integration/test_container_create.py index 45f2f202..376f9282 100644 --- a/podman/tests/integration/test_container_create.py +++ b/podman/tests/integration/test_container_create.py @@ -57,7 +57,7 @@ def test_container_directory_volume_mount(self): with self.subTest("Check bind mount"): volumes = { "/etc/hosts": dict(bind="/test_ro", mode='ro'), - "/etc/hosts": dict(bind="/test_rw", mode='rw'), + "/etc/hosts": dict(bind="/test_rw", mode='rw'), # noqa: F601 } container = self.client.containers.create( self.alpine_image, command=["cat", "/test_ro", "/test_rw"], volumes=volumes diff --git a/podman/tests/integration/test_images.py b/podman/tests/integration/test_images.py index 298d13ec..91db11a0 100644 --- a/podman/tests/integration/test_images.py +++ b/podman/tests/integration/test_images.py @@ -13,6 +13,7 @@ # under the License. # """Images integration tests.""" + import io import queue import tarfile diff --git a/podman/tests/integration/test_networks.py b/podman/tests/integration/test_networks.py index 0b5d44d1..c034ca8d 100644 --- a/podman/tests/integration/test_networks.py +++ b/podman/tests/integration/test_networks.py @@ -13,6 +13,7 @@ # under the License. # """Network integration tests.""" + import os import random import unittest diff --git a/podman/tests/integration/utils.py b/podman/tests/integration/utils.py index 78aea63a..262bf86e 100644 --- a/podman/tests/integration/utils.py +++ b/podman/tests/integration/utils.py @@ -13,6 +13,7 @@ # under the License. # """Integration Test Utils""" + import logging import os import shutil @@ -97,9 +98,7 @@ def consume_lines(pipe, consume_fn): def consume(line: str): logger.debug(line.strip("\n") + f" refid={self.reference_id}") - self.proc = subprocess.Popen( - self.cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT - ) # pylint: disable=consider-using-with + self.proc = subprocess.Popen(self.cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) # pylint: disable=consider-using-with threading.Thread(target=consume_lines, args=[self.proc.stdout, consume]).start() if not check_socket: diff --git a/podman/tests/unit/test_imagesmanager.py b/podman/tests/unit/test_imagesmanager.py index 4906daf2..cab896c7 100644 --- a/podman/tests/unit/test_imagesmanager.py +++ b/podman/tests/unit/test_imagesmanager.py @@ -627,7 +627,8 @@ def test_list_with_name_overrides_reference_filter(self, mock): # The name parameter should override the reference filter images = self.client.images.list( - name="fedora", filters={"reference": "ubuntu"} # This should be overridden + name="fedora", + filters={"reference": "ubuntu"}, # This should be overridden ) self.assertEqual(len(images), 1) diff --git a/pyproject.toml b/pyproject.toml index 9db36747..5361b2fd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,4 +30,3 @@ log_cli = true log_cli_level = "DEBUG" log_cli_format = "%(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)" log_cli_date_format = "%Y-%m-%d %H:%M:%S" - diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 00000000..02b60ac5 --- /dev/null +++ b/ruff.toml @@ -0,0 +1,50 @@ + +line-length = 100 +[format] +exclude = [ + ".git", + ".venv", + ".history", + "build", + "dist", + "docs", + "hack", +] +quote-style = "preserve" +[lint] +select = [ + # More stuff here https://docs.astral.sh/ruff/rules/ + "F", # Pyflakes + "E", # Pycodestyle Error + "W", # Pycodestyle Warning + "N", # PEP8 Naming + # TODO "UP", # Pyupgrade + # TODO "ANN", + # TODO "S", # Bandit + # "B", # Bugbear + "A", # flake-8-builtins + "YTT", # flake-8-2020 + "PLC", # Pylint Convention + "PLE", # Pylint Error + "PLW", # Pylint Warning +] +# Some checks should be enabled for code sanity disabled now +# to avoid changing too many lines +ignore = [ + "F821", # TODO Undefined name + "F541", # TODO f-string is missing placeholders + "F401", # TODO Module imported but unused + "F841", # TODO Local variable is assigned to but never used + "E402", # TODO Module level import not at top of file + "E741", # TODO ambiguous variable name + "E722", # TODO do not use bare 'except' + "E501", # TODO line too long + "N818", # TODO Error Suffix in exception name + "N80", # TODO Invalid Name + "ANN10", # Missing type annotation + "PLW2901", # TODO Redefined Loop Name +] +[lint.per-file-ignores] +"podman/tests/*.py" = ["S"] +[lint.flake8-builtins] +builtins-ignorelist = ["copyright", "all"] diff --git a/test-requirements.txt b/test-requirements.txt index b208312e..1a70e359 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,9 +1,8 @@ # Any changes should be copied into pyproject.toml -r requirements.txt -black +ruff coverage fixtures -pylint pytest requests-mock >= 1.11.0 tox diff --git a/tox.ini b/tox.ini index 94d6b07a..66e6288a 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] minversion = 3.2.0 -envlist = pylint,coverage,py39,py310,py311,py312,py313 +envlist = coverage,py39,py310,py311,py312,py313 ignore_basepython_conflict = true [testenv] @@ -17,21 +17,25 @@ setenv = [testenv:venv] commands = {posargs} -[testenv:pylint] -depends = py310 -basepython = python3.10 -allowlist_externals = pylint -commands = pylint podman +[testenv:lint] +depends = ruff +allowlist_externals = ruff +commands = ruff check --diff + +# TODO: add pylint as alias of lint for compatibility [testenv:coverage] commands = coverage run -m pytest coverage report -m --skip-covered --fail-under=80 --omit=podman/tests/* --omit=.tox/* -[testenv:black] -deps = black +[testenv:format] +deps = ruff +allowlist_externals = ruff commands = - black --diff --check . + ruff format --diff + +# TODO: add black as alias of format for compatibility [testenv:black-format] deps = black