diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml index 90f86dfc4..5cb12eb7d 100644 --- a/.github/workflows/style.yml +++ b/.github/workflows/style.yml @@ -17,10 +17,10 @@ jobs: steps: - name: "๐Ÿ”€ Checkout repository" - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: '๐Ÿ Initialize Python' - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: "3.8" @@ -37,10 +37,10 @@ jobs: steps: - name: "๐Ÿ”€ Checkout repository" - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: '๐Ÿ Initialize Python' - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: "3.8" @@ -51,3 +51,16 @@ jobs: uses: isort/isort-action@master with: configuration: --check --diff --color + + ruff: + + name: ruff + runs-on: ubuntu-latest + + steps: + + - name: "๐Ÿ”€ Checkout repository" + uses: actions/checkout@v4 + + - name: "๐Ÿ“ Ruff" + uses: chartboost/ruff-action@v1 diff --git a/.gitignore b/.gitignore index 707a422a0..cee7f19c9 100644 --- a/.gitignore +++ b/.gitignore @@ -136,3 +136,6 @@ dmypy.json # setuptools_scm dynamic version src/jaxsim/_version.py + +# ruff +.ruff_cache/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fc6f215ce..1ce3ee278 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,3 +19,8 @@ repos: hooks: - id: isort name: isort (python) + + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.3.2 + hooks: + - id: ruff diff --git a/docs/conf.py b/docs/conf.py index ba4604da5..7ba001bd5 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,6 +1,5 @@ # Configuration file for the Sphinx documentation builder. import os -import pathlib import sys from pkg_resources import get_distribution @@ -23,8 +22,6 @@ def _recursive_add_annotations_import(): if "READTHEDOCS" in os.environ: _recursive_add_annotations_import() -import jaxsim - # -- Version information sys.path.insert(0, os.path.abspath(".")) diff --git a/pyproject.toml b/pyproject.toml index f44fd14b1..d3b070f38 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,9 +1,9 @@ [build-system] build-backend = "setuptools.build_meta" requires = [ - "wheel", - "setuptools>=64", - "setuptools_scm[toml]>=8", + "wheel", + "setuptools>=64", + "setuptools_scm[toml]>=8", ] [tool.setuptools_scm] @@ -14,12 +14,55 @@ version_file = "src/jaxsim/_version.py" line-length = 88 [tool.isort] -profile = "black" multi_line_output = 3 +profile = "black" [tool.pytest.ini_options] -minversion = "6.0" addopts = "-rsxX -v --strict-markers" +minversion = "6.0" +preview = true testpaths = [ - "tests", + "tests", ] + +target-version = "py311" + +[tool.ruff] +exclude = [ + ".git", + ".pytest_cache", + ".ruff_cache", + ".vscode", + ".devcontainer", + "__pycache__", +] +preview = true + +[tool.ruff.lint] +# https://docs.astral.sh/ruff/rules/ +ignore = [ + "B008", # Function call in default argument + "B024", # Abstract base class without abstract methods + "B904", # Raise without from inside exception + "B905", # Zip without explicit strict + "E402", # Module level import not at top of file + "E501", # Line too long + "E731", # Do not assign a `lambda` expression, use a `def` + "E741", # Ambiguous variable name + "F841", # Local variable is assigned to but never used + "I001", # Import block is unsorted or unformatted +] +select = [ + "B", + "E", + "F", + "I", + "W", + "YTT", +] + +[tool.ruff.lint.per-file-ignores] +# Ignore `E402` (import violations) in all `__init__.py` files +"**/{tests,docs,tools}/*" = ["E402"] +"**/{tests}/*" = ["B007"] +"__init__.py" = ["F401"] diff --git a/src/jaxsim/api/common.py b/src/jaxsim/api/common.py index 2c1c12bc6..fe958156a 100644 --- a/src/jaxsim/api/common.py +++ b/src/jaxsim/api/common.py @@ -89,7 +89,7 @@ def inertial_to_other_representation( transform: jtp.Matrix, is_force: bool = False, ) -> jtp.Array: - """ + r""" Convert a 6D quantity from inertial-fixed to another representation. Args: @@ -155,7 +155,7 @@ def other_representation_to_inertial( transform: jtp.Matrix, is_force: bool = False, ) -> jtp.Array: - """ + r""" Convert a 6D quantity from another representation to inertial-fixed. Args: diff --git a/src/jaxsim/api/data.py b/src/jaxsim/api/data.py index 13170cba3..7923cfb72 100644 --- a/src/jaxsim/api/data.py +++ b/src/jaxsim/api/data.py @@ -415,9 +415,9 @@ def base_velocity(self) -> jtp.Vector: @jax.jit def generalized_position(self) -> tuple[jtp.Matrix, jtp.Vector]: - """ + r""" Get the generalized position - :math:`\mathbf{q} = ({}^W \mathbf{H}_B, \mathbf{s}) \in \text{SO}(3) \times \mathbb{R}^n`. + :math:`\\mathbf{q} = ({}^W \\mathbf{H}_B, \\mathbf{s}) \\in \text{SO}(3) \times \\mathbb{R}^n`. Returns: A tuple containing the base transform and the joint positions. @@ -427,9 +427,9 @@ def generalized_position(self) -> tuple[jtp.Matrix, jtp.Vector]: @jax.jit def generalized_velocity(self) -> jtp.Vector: - """ + r""" Get the generalized velocity - :math:`\boldsymbol{\nu} = (\boldsymbol{v}_{W,B};\, \boldsymbol{\omega}_{W,B};\, \mathbf{s}) \in \mathbb{R}^{6+n}` + :math:`\boldsymbol{\nu} = (\boldsymbol{v}_{W,B};\\, \boldsymbol{\\omega}_{W,B};\\, \\mathbf{s}) \\in \\mathbb{R}^{6+n}` Returns: The generalized velocity in the active representation. diff --git a/src/jaxsim/api/model.py b/src/jaxsim/api/model.py index a6634cf5e..1d46272a2 100644 --- a/src/jaxsim/api/model.py +++ b/src/jaxsim/api/model.py @@ -937,7 +937,7 @@ def to_inertial(C_vฬ‡_WB, W_H_C, C_v_WB, W_v_WC): def free_floating_gravity_forces( model: JaxSimModel, data: js.data.JaxSimModelData ) -> jtp.Vector: - """ + r""" Compute the free-floating gravity forces :math:`g(\mathbf{q})` of the model. Args: @@ -987,7 +987,7 @@ def free_floating_bias_forces( model: JaxSimModel, data: js.data.JaxSimModelData ) -> jtp.Vector: """ - Compute the free-floating bias forces :math:`h(\mathbf{q}, \boldsymbol{\nu})` + Compute the free-floating bias forces :math:`h(\\mathbf{q}, \boldsymbol{\nu})` of the model. Args: diff --git a/src/jaxsim/api/ode.py b/src/jaxsim/api/ode.py index f1aa82c4f..a2a98043e 100644 --- a/src/jaxsim/api/ode.py +++ b/src/jaxsim/api/ode.py @@ -8,7 +8,6 @@ import jaxsim.typing as jtp from jaxsim.integrators import Time from jaxsim.math import Quaternion -from jaxsim.utils import Mutability from .common import VelRepr from .ode_data import ODEState diff --git a/src/jaxsim/integrators/common.py b/src/jaxsim/integrators/common.py index e33eab5fd..26e9cb47a 100644 --- a/src/jaxsim/integrators/common.py +++ b/src/jaxsim/integrators/common.py @@ -324,7 +324,7 @@ def integrate_rk_stage( def post_process_state( cls, x0: State, t0: Time, xf: NextState, dt: TimeStep ) -> NextState: - """ + r""" Post-process the integrated state at :math:`t_f = t_0 + \Delta t`. Args: @@ -529,7 +529,7 @@ def butcher_tableau_supports_fsal( # Return the index of the row of A providing the fsal derivative (that is the # possibly intermediate kแตข derivative). # Note that if multiple rows match (it should not), we return the first match. - return True, int(jnp.where(rows_of_A_with_fsal == True)[0].tolist()[0]) + return True, int(jnp.where(rows_of_A_with_fsal)[0].tolist()[0]) class ExplicitRungeKuttaSO3Mixin: diff --git a/src/jaxsim/math/transform.py b/src/jaxsim/math/transform.py index e7492545e..f7a5031dc 100644 --- a/src/jaxsim/math/transform.py +++ b/src/jaxsim/math/transform.py @@ -1,4 +1,3 @@ -import jax import jax.numpy as jnp import jaxlie diff --git a/src/jaxsim/mujoco/loaders.py b/src/jaxsim/mujoco/loaders.py index cf6cb17a5..2d26c9b13 100644 --- a/src/jaxsim/mujoco/loaders.py +++ b/src/jaxsim/mujoco/loaders.py @@ -102,7 +102,7 @@ def add_floating_joint( if root.find(f".//joint[@name='{floating_joint_name}']") is not None: msg = f"The URDF already has a floating joint '{floating_joint_name}'" - warnings.warn(msg) + warnings.warn(msg, stacklevel=2) return ET.tostring(root, pretty_print=True).decode() # Create the "world" link if it doesn't exist. diff --git a/src/jaxsim/mujoco/model.py b/src/jaxsim/mujoco/model.py index e24cb30a1..845f6bb90 100644 --- a/src/jaxsim/mujoco/model.py +++ b/src/jaxsim/mujoco/model.py @@ -7,6 +7,8 @@ import numpy.typing as npt from scipy.spatial.transform import Rotation +import jaxsim.typing as jtp + HeightmapCallable = Callable[[jtp.FloatLike, jtp.FloatLike], jtp.FloatLike] diff --git a/src/jaxsim/parsers/kinematic_graph.py b/src/jaxsim/parsers/kinematic_graph.py index 7b3021f47..5841e35d8 100644 --- a/src/jaxsim/parsers/kinematic_graph.py +++ b/src/jaxsim/parsers/kinematic_graph.py @@ -268,7 +268,7 @@ def reduce(self, considered_joints: List[str]) -> "KinematicGraph": # Return early if there is no action to take if len(joint_names_to_remove) == 0: - logging.info(f"The kinematic graph doesn't need to be reduced") + logging.info("The kinematic graph doesn't need to be reduced") return copy.deepcopy(self) # Check if all considered joints are part of the full kinematic graph diff --git a/src/jaxsim/utils/jaxsim_dataclass.py b/src/jaxsim/utils/jaxsim_dataclass.py index 63eab70e3..2c760b0bc 100644 --- a/src/jaxsim/utils/jaxsim_dataclass.py +++ b/src/jaxsim/utils/jaxsim_dataclass.py @@ -1,6 +1,5 @@ import abc import contextlib -import copy import dataclasses import functools from collections.abc import Iterator diff --git a/tests/conftest.py b/tests/conftest.py index c2a10b141..20e75b987 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,7 +2,6 @@ import pathlib import jax -import jax.numpy as jnp import pytest import rod @@ -176,14 +175,12 @@ def jaxsim_model_ergocub() -> js.model.JaxSimModel: The JaxSim model of the ErgoCub robot. """ - os_environ_original = os.environ.copy() - try: os.environ["ROBOT_DESCRIPTION_COMMIT"] = "v0.7.1" import robot_descriptions.ergocub_description finally: - os.environ = os_environ_original + _ = os.environ.pop("ROBOT_DESCRIPTION_COMMIT", None) model_urdf_path = pathlib.Path( robot_descriptions.ergocub_description.URDF_PATH.replace( diff --git a/tests/test_pytree.py b/tests/test_pytree.py index e3059203a..633872197 100644 --- a/tests/test_pytree.py +++ b/tests/test_pytree.py @@ -2,7 +2,6 @@ from contextlib import redirect_stdout import jax -import jax.numpy as jnp import rod.builder.primitives import rod.urdf.exporter