diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 424727c8990..f69eb4c0758 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,20 +4,25 @@ # SPDX-License-Identifier: BSD-3-Clause repos: + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.14.10 + hooks: + # Run the linter + - id: ruff + args: ["--fix"] + # Run the formatter + # - id: ruff-format - repo: https://github.com/python/black rev: 24.3.0 hooks: - id: black - - repo: https://github.com/pycqa/flake8 - rev: 7.1.0 + - repo: https://github.com/pycqa/isort + rev: 5.13.2 hooks: - - id: flake8 - additional_dependencies: - - flake8-simplify - - flake8-return - - Flake8-pyproject + - id: isort + name: isort (python) - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: trailing-whitespace - id: check-symlinks @@ -33,20 +38,8 @@ repos: - id: check-shebang-scripts-are-executable - id: detect-private-key - id: debug-statements - - repo: https://github.com/pycqa/isort - rev: 5.13.2 - hooks: - - id: isort - name: isort (python) - - repo: https://github.com/asottile/pyupgrade - rev: v3.15.1 - hooks: - - id: pyupgrade - args: ["--py310-plus"] - # FIXME: This is a hack because Pytorch does not like: torch.Tensor | dict aliasing - exclude: "source/isaaclab/isaaclab/envs/common.py|source/isaaclab/isaaclab/ui/widgets/image_plot.py|source/isaaclab_tasks/isaaclab_tasks/direct/humanoid_amp/motions/motion_loader.py" - repo: https://github.com/codespell-project/codespell - rev: v2.2.6 + rev: v2.4.1 hooks: - id: codespell additional_dependencies: @@ -58,7 +51,7 @@ repos: # hooks: # - id: pyright - repo: https://github.com/Lucas-C/pre-commit-hooks - rev: v1.5.1 + rev: v1.5.5 hooks: - id: insert-license files: \.(py|ya?ml)$ @@ -70,7 +63,7 @@ repos: exclude: "source/isaaclab_mimic/|scripts/imitation_learning/isaaclab_mimic/" # Apache 2.0 license for mimic files - repo: https://github.com/Lucas-C/pre-commit-hooks - rev: v1.5.1 + rev: v1.5.5 hooks: - id: insert-license files: ^(source/isaaclab_mimic|scripts/imitation_learning/isaaclab_mimic)/.*\.py$ diff --git a/.vscode/tools/settings.template.json b/.vscode/tools/settings.template.json index f511f3fddb4..c238bc4a85b 100644 --- a/.vscode/tools/settings.template.json +++ b/.vscode/tools/settings.template.json @@ -63,9 +63,8 @@ "python.languageServer": "Pylance", // We use "black" as a formatter: "black-formatter.args": ["--line-length", "120", "--unstable"], - // Use flake8 for linting - "flake8.enabled": true, - "flake8.args": ["--config", "${workspaceFolder}/pyproject.toml"], + // Use ruff as a linter + "ruff.configuration": "${workspaceFolder}/pyproject.toml", // Use docstring generator "autoDocstring.docstringFormat": "google", "autoDocstring.guessTypes": true, diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 1759c58ded6..09fde19be7c 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -4,7 +4,7 @@ # SPDX-License-Identifier: BSD-3-Clause # Here we set the parts that would -# be re-used between services to an +# be reused between services to an # extension field # https://docs.docker.com/compose/compose-file/compose-file-v3/#extension-fields x-default-isaac-lab-volumes: &default-isaac-lab-volumes diff --git a/docs/licenses/dependencies/ruff-license.txt b/docs/licenses/dependencies/ruff-license.txt new file mode 100644 index 00000000000..655a0c76fc5 --- /dev/null +++ b/docs/licenses/dependencies/ruff-license.txt @@ -0,0 +1,430 @@ +MIT License + +Copyright (c) 2022 Charles Marsh + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +end of terms and conditions + +The externally maintained libraries from which parts of the Software is derived +are: + +- autoflake, licensed as follows: + """ + Copyright (C) 2012-2018 Steven Myint + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal in + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + """ + +- autotyping, licensed as follows: + """ + MIT License + + Copyright (c) 2023 Jelle Zijlstra + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + """ + +- Flake8, licensed as follows: + """ + == Flake8 License (MIT) == + + Copyright (C) 2011-2013 Tarek Ziade + Copyright (C) 2012-2016 Ian Cordasco + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal in + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + """ + +- flake8-eradicate, licensed as follows: + """ + MIT License + + Copyright (c) 2018 Nikita Sobolev + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + """ + +- flake8-pyi, licensed as follows: + """ + The MIT License (MIT) + + Copyright (c) 2016 Łukasz Langa + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + """ + +- flake8-simplify, licensed as follows: + """ + MIT License + + Copyright (c) 2020 Martin Thoma + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + """ + +- isort, licensed as follows: + """ + The MIT License (MIT) + + Copyright (c) 2013 Timothy Edmund Crosley + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + """ + +- pygrep-hooks, licensed as follows: + """ + Copyright (c) 2018 Anthony Sottile + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + """ + +- pycodestyle, licensed as follows: + """ + Copyright © 2006-2009 Johann C. Rocholl + Copyright © 2009-2014 Florent Xicluna + Copyright © 2014-2020 Ian Lee + + Licensed under the terms of the Expat License + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + """ + +- pydocstyle, licensed as follows: + """ + Copyright (c) 2012 GreenSteam, + + Copyright (c) 2014-2020 Amir Rachum, + + Copyright (c) 2020 Sambhav Kothari, + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal in + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + """ + +- Pyflakes, licensed as follows: + """ + Copyright 2005-2011 Divmod, Inc. + Copyright 2013-2014 Florent Xicluna + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + """ + +- Pyright, licensed as follows: + """ + MIT License + + Pyright - A static type checker for the Python language + Copyright (c) Microsoft Corporation. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE + """ + +- pyupgrade, licensed as follows: + """ + Copyright (c) 2017 Anthony Sottile + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + """ + +- rome/tools, licensed under the MIT license: + """ + MIT License + + Copyright (c) Rome Tools, Inc. and its affiliates. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + """ + +- RustPython, licensed as follows: + """ + MIT License + + Copyright (c) 2020 RustPython Team + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + """ + +- rust-analyzer/text-size, licensed under the MIT license: + """ + Permission is hereby granted, free of charge, to any + person obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the + Software without restriction, including without + limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of + the Software, and to permit persons to whom the Software + is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice + shall be included in all copies or substantial portions + of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF + ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + """ diff --git a/docs/licenses/dependencies/ruff-pre-commit-license.txt b/docs/licenses/dependencies/ruff-pre-commit-license.txt new file mode 100644 index 00000000000..c16d8bb1db2 --- /dev/null +++ b/docs/licenses/dependencies/ruff-pre-commit-license.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Astral Software Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/docs/source/deployment/docker.rst b/docs/source/deployment/docker.rst index 9f214ce49d4..2c4aeb7cbea 100644 --- a/docs/source/deployment/docker.rst +++ b/docs/source/deployment/docker.rst @@ -47,7 +47,7 @@ needed to run Isaac Lab inside a Docker container. A subset of these are summari Dockerfiles which end with something else, (i.e. ``Dockerfile.ros2``) build an `image extension <#isaac-lab-image-extensions>`_. * **docker-compose.yaml**: Creates mounts to allow direct editing of Isaac Lab code from the host machine that runs the container. It also creates several named volumes such as ``isaac-cache-kit`` to - store frequently re-used resources compiled by Isaac Sim, such as shaders, and to retain logs, data, and documents. + store frequently reused resources compiled by Isaac Sim, such as shaders, and to retain logs, data, and documents. * **.env.base**: Stores environment variables required for the ``base`` build process and the container itself. ``.env`` files which end with something else (i.e. ``.env.ros2``) define these for `image extension <#isaac-lab-image-extensions>`_. * **docker-compose.cloudxr-runtime.patch.yaml**: A patch file that is applied to enable CloudXR Runtime support for diff --git a/docs/source/overview/developer-guide/vs_code.rst b/docs/source/overview/developer-guide/vs_code.rst index 5464e1e7a64..cc883131cfe 100644 --- a/docs/source/overview/developer-guide/vs_code.rst +++ b/docs/source/overview/developer-guide/vs_code.rst @@ -80,15 +80,14 @@ refer to the `VSCode documentation `_ as a formatter and `flake8 `_ as a linter. These are configured in the ``.vscode/settings.json`` file: +We use `black `_ as a formatter and `ruff `_ as a linter. These are configured in the ``.vscode/settings.json`` file: .. code-block:: json { "black-formatter.args": ["--line-length", "120", "--unstable"], - "flake8.enabled": true, - "flake8.args": ["--config", "${workspaceFolder}/pyproject.toml"], + "ruff.configuration": "${workspaceFolder}/pyproject.toml", } The black formatter will automatically format your code to match the project's style guide (120 character line length). -The flake8 linter will show warnings and errors in your code to help you follow Python best practices and the project's coding standards. +The ruff linter will show warnings and errors in your code to help you follow Python best practices and the project's coding standards. diff --git a/docs/source/refs/contributing.rst b/docs/source/refs/contributing.rst index bc2d60c426a..3b0f534b71e 100644 --- a/docs/source/refs/contributing.rst +++ b/docs/source/refs/contributing.rst @@ -516,8 +516,7 @@ We use the following tools for maintaining code quality: * `pre-commit `__: Runs a list of formatters and linters over the codebase. * `black `__: The uncompromising code formatter. -* `flake8 `__: A wrapper around PyFlakes, pycodestyle and - McCabe complexity checker. +* `ruff `__: An extremely fast Python linter and formatter. Please check `here `__ for instructions to set these up. To run over the entire repository, please execute the diff --git a/docs/source/refs/snippets/code_skeleton.py b/docs/source/refs/snippets/code_skeleton.py index ec9c057e726..0c3e456b330 100644 --- a/docs/source/refs/snippets/code_skeleton.py +++ b/docs/source/refs/snippets/code_skeleton.py @@ -3,8 +3,6 @@ # # SPDX-License-Identifier: BSD-3-Clause -import os -import sys from typing import ClassVar diff --git a/docs/source/refs/snippets/tutorial_modify_direct_rl_env.py b/docs/source/refs/snippets/tutorial_modify_direct_rl_env.py index 98e1765a11d..e839abf2009 100644 --- a/docs/source/refs/snippets/tutorial_modify_direct_rl_env.py +++ b/docs/source/refs/snippets/tutorial_modify_direct_rl_env.py @@ -3,6 +3,7 @@ # # SPDX-License-Identifier: BSD-3-Clause +# ruff: noqa # fmt: off # [start-init-import] diff --git a/pyproject.toml b/pyproject.toml index 0118003948a..1e0bca94428 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,45 +9,7 @@ target-version = ["py311"] preview = true unstable = true -[tool.flake8] -show-source = true -statistics = true - -per-file-ignores = [ - "*/__init__.py:F401", -] - -ignore = [ - "E402", # Module level import not at top of file - "E501", # Line too long - "F403", # Unable to detect undefined names - "W503", # Line break before binary operator - "E203", # Whitespace before ':' (Black conflict) - "D401", # First line should be in imperative mood - "R504", # Unnecessary variable assignment before return - "R505", # Unnecessary elif after return statement - "SIM102", # Use a single if-statement instead of nested if-statements - "SIM117", # Merge with statements for context managers that have same scope. - "SIM118", # Checks for key-existence checks against dict.keys() calls. -] - -max-line-length = 120 -max-complexity = 30 - -exclude = [ - "_**", - ".vscode", - ".git", - "docs/**", -] - -# docstrings -docstring-convention = "google" - -# annotations -suppress-none-returning = true -allow-star-arg-any = true - +# TODO: Remove this once isort is removed from the project [tool.isort] profile = "black" @@ -135,6 +97,113 @@ known_task_firstparty = "isaaclab_tasks" # Imports from the local folder known_local_folder = "config" +[tool.ruff] +line-length = 120 +target-version = "py310" + +# Exclude directories +extend-exclude = [ + "logs", + "_isaac_sim", + ".vscode", + "_*", + ".git", +] + +[tool.ruff.lint] +# Enable flake8 rules and other useful ones +select = [ + "E", # pycodestyle errors + "W", # pycodestyle warnings + "F", # pyflakes + # "I", # isort + "UP", # pyupgrade + "C90", # mccabe complexity + # "D", # pydocstyle + "SIM", # flake8-simplify + "RET", # flake8-return +] + +# Ignore specific rules (matching your flake8 config) +ignore = [ + "E402", # Module level import not at top of file + "E501", # Line too long (handled by formatter) + "E203", # Whitespace before ':' (conflicts with formatter) + "D401", # First line should be in imperative mood + "RET504", # Unnecessary variable assignment before return statement + "RET505", # Unnecessary elif after return statement + "SIM102", # Use a single if-statement instead of nested if-statements + "SIM103", # Return the negated condition directly + "SIM108", # Use ternary operator instead of if-else statement + "SIM117", # Merge with statements for context managers + "SIM118", # Use {key} in {dict} instead of {key} in {dict}.keys() + "UP006", # Use 'dict' instead of 'Dict' type annotation + "UP018", # Unnecessary `float` call (rewrite as a literal) +] + +[tool.ruff.lint.per-file-ignores] +"__init__.py" = ["F401"] # Allow unused imports in __init__.py files + +[tool.ruff.lint.mccabe] +max-complexity = 30 + +[tool.ruff.lint.pydocstyle] +convention = "google" + +[tool.ruff.lint.isort] +# Match isort behavior +combine-as-imports = true +order-by-type = true +from-first = false + +# Custom import sections with separate sections for each Isaac Lab extension +section-order = [ + "future", + "standard-library", + "third-party", + # Group omniverse extensions separately since they are run-time dependencies + # which are pulled in by Isaac Lab extensions + "omniverse-extensions", + # Group Isaac Lab extensions together since they are all part of the Isaac Lab project + "isaaclab", + "isaaclab-assets", + "isaaclab-rl", + "isaaclab-mimic", + "isaaclab-tasks", + # First-party is reserved for project templates + "first-party", + "local-folder", +] + +[tool.ruff.lint.isort.sections] +# Define what belongs in each custom section + +"omniverse-extensions" = [ + "isaacsim", + "omni", + "pxr", + "carb", + "usdrt", + "Semantics", + "curobo", +] + +"isaaclab" = ["isaaclab"] +"isaaclab-assets" = ["isaaclab_assets"] +"isaaclab-rl" = ["isaaclab_rl"] +"isaaclab-mimic" = ["isaaclab_mimic"] +"isaaclab-tasks" = ["isaaclab_tasks"] + +[tool.ruff.format] +# Use Black-compatible formatting +quote-style = "double" +indent-style = "space" +skip-magic-trailing-comma = false +line-ending = "auto" +preview = true + +# docstring-code-format = true + [tool.pyright] include = ["source", "scripts"] @@ -167,7 +236,8 @@ reportPrivateUsage = "warning" skip = '*.usd,*.usda,*.usdz,*.svg,*.png,_isaac_sim*,*.bib,*.css,*/_build' quiet-level = 0 # the world list should always have words in lower case -ignore-words-list = "haa,slq,collapsable,buss,reacher" +ignore-words-list = "haa,slq,collapsable,buss,reacher,thirdparty" + [tool.pytest.ini_options] diff --git a/scripts/demos/h1_locomotion.py b/scripts/demos/h1_locomotion.py index 0285fc4f07e..97c58af05b3 100644 --- a/scripts/demos/h1_locomotion.py +++ b/scripts/demos/h1_locomotion.py @@ -41,6 +41,7 @@ simulation_app = app_launcher.app """Rest everything follows.""" + import torch import carb diff --git a/scripts/demos/pick_and_place.py b/scripts/demos/pick_and_place.py index a652168c5a2..d3c22dc18a6 100644 --- a/scripts/demos/pick_and_place.py +++ b/scripts/demos/pick_and_place.py @@ -21,6 +21,8 @@ app_launcher = AppLauncher(args_cli) simulation_app = app_launcher.app +"""Rest everything follows.""" + import torch from collections.abc import Sequence diff --git a/scripts/imitation_learning/isaaclab_mimic/generate_dataset.py b/scripts/imitation_learning/isaaclab_mimic/generate_dataset.py index 3f83fa171ee..3c700e97df6 100644 --- a/scripts/imitation_learning/isaaclab_mimic/generate_dataset.py +++ b/scripts/imitation_learning/isaaclab_mimic/generate_dataset.py @@ -7,7 +7,6 @@ Main data generation script. """ - """Launch Isaac Sim Simulator first.""" import argparse diff --git a/scripts/reinforcement_learning/ray/hyperparameter_tuning/vision_cartpole_cfg.py b/scripts/reinforcement_learning/ray/hyperparameter_tuning/vision_cartpole_cfg.py index f48085134ee..f43ae7ecaaa 100644 --- a/scripts/reinforcement_learning/ray/hyperparameter_tuning/vision_cartpole_cfg.py +++ b/scripts/reinforcement_learning/ray/hyperparameter_tuning/vision_cartpole_cfg.py @@ -76,7 +76,7 @@ def __call__(self, trial_id: str, result: dict[str, Any]) -> bool: out_of_bounds = result.get("Episode/Episode_Termination/cart_out_of_bounds") # Mark the trial for stopping if conditions are met - if 20 <= iter and out_of_bounds is not None and out_of_bounds > 0.85: + if iter >= 20 and out_of_bounds is not None and out_of_bounds > 0.85: self._bad_trials.add(trial_id) return trial_id in self._bad_trials diff --git a/scripts/reinforcement_learning/ray/launch.py b/scripts/reinforcement_learning/ray/launch.py index a9f621cb9b1..68d086d3233 100644 --- a/scripts/reinforcement_learning/ray/launch.py +++ b/scripts/reinforcement_learning/ray/launch.py @@ -3,15 +3,6 @@ # # SPDX-License-Identifier: BSD-3-Clause -import argparse -import pathlib -import subprocess -import yaml - -import util -from jinja2 import Environment, FileSystemLoader -from kubernetes import config - """This script helps create one or more KubeRay clusters. Usage: @@ -34,6 +25,18 @@ --num_workers 1 2 --num_clusters 1 \ --worker_accelerator nvidia-l4 nvidia-tesla-t4 --gpu_per_worker 1 2 4 """ + +import argparse +import pathlib +import subprocess +import yaml + +from jinja2 import Environment, FileSystemLoader +from kubernetes import config + +# Local imports +import util # isort: skip + RAY_DIR = pathlib.Path(__file__).parent diff --git a/scripts/tools/merge_hdf5_datasets.py b/scripts/tools/merge_hdf5_datasets.py index e29db100e2e..e38555dcb11 100644 --- a/scripts/tools/merge_hdf5_datasets.py +++ b/scripts/tools/merge_hdf5_datasets.py @@ -30,7 +30,6 @@ def merge_datasets(): copy_attributes = True for filepath in args_cli.input_files: - with h5py.File(filepath, "r") as input: for episode, data in input["data"].items(): input.copy(f"data/{episode}", output, f"data/demo_{episode_idx}") diff --git a/scripts/tools/replay_demos.py b/scripts/tools/replay_demos.py index 680d75deea5..de0582045cb 100644 --- a/scripts/tools/replay_demos.py +++ b/scripts/tools/replay_demos.py @@ -250,7 +250,7 @@ def main(): if next_episode_index is not None: replayed_episode_count += 1 current_episode_indices[env_id] = next_episode_index - print(f"{replayed_episode_count :4}: Loading #{next_episode_index} episode to env_{env_id}") + print(f"{replayed_episode_count:4}: Loading #{next_episode_index} episode to env_{env_id}") episode_data = dataset_file_handler.load_episode( episode_names[next_episode_index], env.device ) @@ -278,7 +278,7 @@ def main(): state_from_dataset = env_episode_data_map[0].get_next_state() if state_from_dataset is not None: print( - f"Validating states at action-index: {env_episode_data_map[0].next_state_index - 1 :4}", + f"Validating states at action-index: {env_episode_data_map[0].next_state_index - 1:4}", end="", ) current_runtime_state = env.scene.get_state(is_relative=True) diff --git a/scripts/tools/test/test_cosmos_prompt_gen.py b/scripts/tools/test/test_cosmos_prompt_gen.py index 859edece9b4..6f2f8d177a5 100644 --- a/scripts/tools/test/test_cosmos_prompt_gen.py +++ b/scripts/tools/test/test_cosmos_prompt_gen.py @@ -16,7 +16,7 @@ @pytest.fixture(scope="class") def temp_templates_file(): """Create temporary templates file.""" - temp_file = tempfile.NamedTemporaryFile(suffix=".json", delete=False) + temp_file = tempfile.NamedTemporaryFile(suffix=".json", delete=False) # noqa: SIM115 # Create test templates test_templates = { @@ -39,7 +39,7 @@ def temp_templates_file(): @pytest.fixture def temp_output_file(): """Create temporary output file.""" - temp_file = tempfile.NamedTemporaryFile(suffix=".txt", delete=False) + temp_file = tempfile.NamedTemporaryFile(suffix=".txt", delete=False) # noqa: SIM115 yield temp_file.name # Cleanup os.remove(temp_file.name) diff --git a/scripts/tools/test/test_hdf5_to_mp4.py b/scripts/tools/test/test_hdf5_to_mp4.py index d013b32d2d9..0dc770e89a0 100644 --- a/scripts/tools/test/test_hdf5_to_mp4.py +++ b/scripts/tools/test/test_hdf5_to_mp4.py @@ -17,7 +17,7 @@ @pytest.fixture(scope="class") def temp_hdf5_file(): """Create temporary HDF5 file with test data.""" - temp_file = tempfile.NamedTemporaryFile(suffix=".h5", delete=False) + temp_file = tempfile.NamedTemporaryFile(suffix=".h5", delete=False) # noqa: SIM115 with h5py.File(temp_file.name, "w") as h5f: # Create test data structure for demo_id in range(2): # Create 2 demos @@ -47,7 +47,7 @@ def temp_hdf5_file(): @pytest.fixture def temp_output_dir(): """Create temporary output directory.""" - temp_dir = tempfile.mkdtemp() + temp_dir = tempfile.mkdtemp() # noqa: SIM115 yield temp_dir # Cleanup for file in os.listdir(temp_dir): diff --git a/scripts/tools/test/test_mp4_to_hdf5.py b/scripts/tools/test/test_mp4_to_hdf5.py index e6e1354ccde..6a8058d3be0 100644 --- a/scripts/tools/test/test_mp4_to_hdf5.py +++ b/scripts/tools/test/test_mp4_to_hdf5.py @@ -18,7 +18,7 @@ @pytest.fixture(scope="class") def temp_hdf5_file(): """Create temporary HDF5 file with test data.""" - temp_file = tempfile.NamedTemporaryFile(suffix=".h5", delete=False) + temp_file = tempfile.NamedTemporaryFile(suffix=".h5", delete=False) # noqa: SIM115 with h5py.File(temp_file.name, "w") as h5f: # Create test data structure for 2 demos for demo_id in range(2): @@ -54,7 +54,7 @@ def temp_hdf5_file(): @pytest.fixture(scope="class") def temp_videos_dir(): """Create temporary MP4 files.""" - temp_dir = tempfile.mkdtemp() + temp_dir = tempfile.mkdtemp() # noqa: SIM115 video_paths = [] for demo_id in range(2): @@ -82,7 +82,7 @@ def temp_videos_dir(): @pytest.fixture def temp_output_file(): """Create temporary output file.""" - temp_file = tempfile.NamedTemporaryFile(suffix=".h5", delete=False) + temp_file = tempfile.NamedTemporaryFile(suffix=".h5", delete=False) # noqa: SIM115 yield temp_file.name # Cleanup os.remove(temp_file.name) diff --git a/scripts/tools/train_and_publish_checkpoints.py b/scripts/tools/train_and_publish_checkpoints.py index 71083dc2e4b..94f26efca2f 100644 --- a/scripts/tools/train_and_publish_checkpoints.py +++ b/scripts/tools/train_and_publish_checkpoints.py @@ -317,7 +317,6 @@ def publish_pretrained_checkpoint(workflow, task_name, force_publish=False): # Not forcing, need to check review results if not force_publish: - # Grab the review if it exists review = get_pretrained_checkpoint_review(workflow, task_name) @@ -355,7 +354,6 @@ def get_job_summary_row(workflow, task_name): def main(): - # Figure out what workflows and tasks we'll be using if args.all: jobs = ["*:*"] @@ -405,7 +403,6 @@ def main(): if __name__ == "__main__": - try: # Run the main function main() diff --git a/source/isaaclab/isaaclab/actuators/actuator_cfg.py b/source/isaaclab/isaaclab/actuators/actuator_cfg.py index c665a222980..5cacb8ffa40 100644 --- a/source/isaaclab/isaaclab/actuators/actuator_cfg.py +++ b/source/isaaclab/isaaclab/actuators/actuator_cfg.py @@ -21,8 +21,7 @@ def __getattr__(name): if new_module is not None: warnings.warn( f"The module actuator_cfg.py is deprecated. Please import {name} directly from the isaaclab.actuators" - " package, " - + f"or from its new module {new_module.__name__}.", + f" package, or from its new module {new_module.__name__}.", DeprecationWarning, stacklevel=2, ) diff --git a/source/isaaclab/isaaclab/controllers/differential_ik.py b/source/isaaclab/isaaclab/controllers/differential_ik.py index bc43603c4be..1126f0c0cf3 100644 --- a/source/isaaclab/isaaclab/controllers/differential_ik.py +++ b/source/isaaclab/isaaclab/controllers/differential_ik.py @@ -209,7 +209,7 @@ def _compute_delta_joint_pos(self, delta_pose: torch.Tensor, jacobian: torch.Ten # U: 6xd, S: dxd, V: d x num-joint U, S, Vh = torch.linalg.svd(jacobian) S_inv = 1.0 / S - S_inv = torch.where(S > min_singular_value, S_inv, torch.zeros_like(S_inv)) + S_inv = torch.where(min_singular_value < S, S_inv, torch.zeros_like(S_inv)) jacobian_pinv = ( torch.transpose(Vh, dim0=1, dim1=2)[:, :, :6] @ torch.diag_embed(S_inv) diff --git a/source/isaaclab/isaaclab/devices/openxr/openxr_device.py b/source/isaaclab/isaaclab/devices/openxr/openxr_device.py index 02961040314..e51c25ae1bb 100644 --- a/source/isaaclab/isaaclab/devices/openxr/openxr_device.py +++ b/source/isaaclab/isaaclab/devices/openxr/openxr_device.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: BSD-3-Clause """OpenXR-powered device for teleoperation and interaction.""" + from __future__ import annotations import contextlib diff --git a/source/isaaclab/isaaclab/devices/teleop_device_factory.py b/source/isaaclab/isaaclab/devices/teleop_device_factory.py index 5f2d393ac69..f7265c41c2c 100644 --- a/source/isaaclab/isaaclab/devices/teleop_device_factory.py +++ b/source/isaaclab/isaaclab/devices/teleop_device_factory.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: BSD-3-Clause """Factory to create teleoperation devices from configuration.""" + import inspect import logging from collections.abc import Callable diff --git a/source/isaaclab/isaaclab/envs/common.py b/source/isaaclab/isaaclab/envs/common.py index b6cc4c044fe..50597aa6383 100644 --- a/source/isaaclab/isaaclab/envs/common.py +++ b/source/isaaclab/isaaclab/envs/common.py @@ -7,7 +7,7 @@ import gymnasium as gym import torch -from typing import Dict, Literal, TypeVar +from typing import Dict, Literal, TypeVar # noqa: UP035 from isaaclab.utils import configclass diff --git a/source/isaaclab/isaaclab/envs/mimic_env_cfg.py b/source/isaaclab/isaaclab/envs/mimic_env_cfg.py index d6dced3bbc9..c2b0f22efc0 100644 --- a/source/isaaclab/isaaclab/envs/mimic_env_cfg.py +++ b/source/isaaclab/isaaclab/envs/mimic_env_cfg.py @@ -9,6 +9,7 @@ """ Base MimicEnvCfg object for Isaac Lab Mimic data generation. """ + import enum from isaaclab.managers.recorder_manager import RecorderManagerBaseCfg diff --git a/source/isaaclab/isaaclab/envs/utils/io_descriptors.py b/source/isaaclab/isaaclab/envs/utils/io_descriptors.py index ae92c31062a..87ec1b450cf 100644 --- a/source/isaaclab/isaaclab/envs/utils/io_descriptors.py +++ b/source/isaaclab/isaaclab/envs/utils/io_descriptors.py @@ -185,7 +185,6 @@ def my_func(env: ManagerBasedEnv, *args, **kwargs): inspect_hooks: list[Callable[..., Any]] = list(on_inspect or []) # handles None def _apply(func: Callable[Concatenate[ManagerBasedEnv, P], R]) -> Callable[Concatenate[ManagerBasedEnv, P], R]: - # Capture the signature of the function sig = inspect.signature(func) diff --git a/source/isaaclab/isaaclab/envs/utils/spaces.py b/source/isaaclab/isaaclab/envs/utils/spaces.py index 9e7687d57e0..27764e9f9b9 100644 --- a/source/isaaclab/isaaclab/envs/utils/spaces.py +++ b/source/isaaclab/isaaclab/envs/utils/spaces.py @@ -61,7 +61,7 @@ def sample_space(space: gym.spaces.Space, device: str, batch_size: int = -1, fil Tensorized sampled space. """ - def tensorize(s, x): + def tensorize(s: gym.spaces.Space, x: Any) -> Any: if isinstance(s, gym.spaces.Box): tensor = torch.tensor(x, device=device, dtype=torch.float32).reshape(batch_size, *s.shape) if fill_value is not None: @@ -89,6 +89,9 @@ def tensorize(s, x): elif isinstance(s, gym.spaces.Tuple): return tuple([tensorize(_s, v) for _s, v in zip(s, x)]) + # If the space is not supported, raise an error + raise ValueError(f"Unsupported Gymnasium space for tensorization: {s}") + sample = (gym.vector.utils.batch_space(space, batch_size) if batch_size > 0 else space).sample() return tensorize(space, sample) diff --git a/source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_caster_camera_data.py b/source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_caster_camera_data.py index d00dab7edf1..d2f26abdbf4 100644 --- a/source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_caster_camera_data.py +++ b/source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_caster_camera_data.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: BSD-3-Clause """Data container for the multi-mesh ray-cast camera sensor.""" + import torch from isaaclab.sensors.camera import CameraData diff --git a/source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_caster_cfg.py b/source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_caster_cfg.py index 2030a894fda..507e2dfabbe 100644 --- a/source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_caster_cfg.py +++ b/source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_caster_cfg.py @@ -6,7 +6,6 @@ """Configuration for the ray-cast sensor.""" - from dataclasses import MISSING from isaaclab.utils import configclass diff --git a/source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_caster_data.py b/source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_caster_data.py index d37c49838bb..b9ae187591b 100644 --- a/source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_caster_data.py +++ b/source/isaaclab/isaaclab/sensors/ray_caster/multi_mesh_ray_caster_data.py @@ -5,6 +5,7 @@ """Data container for the multi-mesh ray-cast sensor.""" + import torch from .ray_caster_data import RayCasterData diff --git a/source/isaaclab/isaaclab/sensors/ray_caster/ray_caster_cfg.py b/source/isaaclab/isaaclab/sensors/ray_caster/ray_caster_cfg.py index 851ac31c85b..1ce3b0c43a9 100644 --- a/source/isaaclab/isaaclab/sensors/ray_caster/ray_caster_cfg.py +++ b/source/isaaclab/isaaclab/sensors/ray_caster/ray_caster_cfg.py @@ -5,7 +5,6 @@ """Configuration for the ray-cast sensor.""" - from dataclasses import MISSING from typing import Literal diff --git a/source/isaaclab/isaaclab/ui/widgets/image_plot.py b/source/isaaclab/isaaclab/ui/widgets/image_plot.py index 8d8304e4a04..6afecca55dd 100644 --- a/source/isaaclab/isaaclab/ui/widgets/image_plot.py +++ b/source/isaaclab/isaaclab/ui/widgets/image_plot.py @@ -3,11 +3,13 @@ # # SPDX-License-Identifier: BSD-3-Clause +from __future__ import annotations + import logging import numpy as np from contextlib import suppress from matplotlib import cm -from typing import TYPE_CHECKING, Optional +from typing import TYPE_CHECKING import omni @@ -53,7 +55,7 @@ class ImagePlot(UIWidgetWrapper): def __init__( self, - image: Optional[np.ndarray] = None, + image: np.ndarray | None = None, label: str = "", widget_height: int = 200, min_value: float = 0.0, @@ -156,7 +158,6 @@ def _get_unit_description(self, min_value: float, max_value: float, median_value ) def _build_widget(self): - with omni.ui.VStack(spacing=3): with omni.ui.HStack(): # Write the leftmost label for what this plot is diff --git a/source/isaaclab/isaaclab/ui/widgets/line_plot.py b/source/isaaclab/isaaclab/ui/widgets/line_plot.py index 90a84e201a1..0768115f97f 100644 --- a/source/isaaclab/isaaclab/ui/widgets/line_plot.py +++ b/source/isaaclab/isaaclab/ui/widgets/line_plot.py @@ -157,7 +157,6 @@ def add_datapoint(self, y_coords: list[float]): """ for idx, y_coord in enumerate(y_coords): - if len(self._y_data[idx]) > self._max_data_points: self._y_data[idx] = self._y_data[idx][1:] diff --git a/source/isaaclab/isaaclab/ui/xr_widgets/scene_visualization.py b/source/isaaclab/isaaclab/ui/xr_widgets/scene_visualization.py index ddd3bda15ff..43cadbc3727 100644 --- a/source/isaaclab/isaaclab/ui/xr_widgets/scene_visualization.py +++ b/source/isaaclab/isaaclab/ui/xr_widgets/scene_visualization.py @@ -158,7 +158,7 @@ class VisualizationManager: # Type aliases for different callback signatures StandardCallback = Callable[["VisualizationManager", "DataCollector"], None] EventCallback = Callable[["VisualizationManager", "DataCollector", Any], None] - CallbackType = Union[StandardCallback, EventCallback] + CallbackType = Union[StandardCallback, EventCallback] # noqa: UP007 class TimeCountdown: """Internal class for managing periodic timer-based callbacks.""" diff --git a/source/isaaclab/isaaclab/utils/array.py b/source/isaaclab/isaaclab/utils/array.py index 7569c7b13f9..e26ff824dd9 100644 --- a/source/isaaclab/isaaclab/utils/array.py +++ b/source/isaaclab/isaaclab/utils/array.py @@ -13,7 +13,7 @@ import warp as wp from typing import Union -TensorData = Union[np.ndarray, torch.Tensor, wp.array] +TensorData = Union[np.ndarray, torch.Tensor, wp.array] # noqa: UP007 """Type definition for a tensor data. Union of numpy, torch, and warp arrays. diff --git a/source/isaaclab/isaaclab/utils/warp/kernels.py b/source/isaaclab/isaaclab/utils/warp/kernels.py index faab41267a5..a37b647f235 100644 --- a/source/isaaclab/isaaclab/utils/warp/kernels.py +++ b/source/isaaclab/isaaclab/utils/warp/kernels.py @@ -135,7 +135,6 @@ def raycast_static_meshes_kernel( # if the ray hit, store the hit data if mesh_query_ray_t.result: - wp.atomic_min(ray_distance, tid_env, tid_ray, mesh_query_ray_t.t) # check if hit distance is less than the current hit distance, only then update the memory # TODO, in theory we could use the output of atomic_min to avoid the non-thread safe next comparison @@ -220,7 +219,6 @@ def raycast_dynamic_meshes_kernel( mesh_query_ray_t = wp.mesh_query_ray(mesh[tid_env, tid_mesh_id], start_pos, direction, max_dist) # if the ray hit, store the hit data if mesh_query_ray_t.result: - wp.atomic_min(ray_distance, tid_env, tid_ray, mesh_query_ray_t.t) # check if hit distance is less than the current hit distance, only then update the memory # TODO, in theory we could use the output of atomic_min to avoid the non-thread safe next comparison diff --git a/source/isaaclab/test/assets/test_rigid_object.py b/source/isaaclab/test/assets/test_rigid_object.py index 3a4d34847e5..2d6574725b9 100644 --- a/source/isaaclab/test/assets/test_rigid_object.py +++ b/source/isaaclab/test/assets/test_rigid_object.py @@ -225,7 +225,6 @@ def test_external_force_buffer(device): # perform simulation for step in range(5): - # initiate force tensor external_wrench_b = torch.zeros(cube_object.num_instances, len(body_ids), 6, device=sim.device) external_wrench_positions_b = torch.zeros(cube_object.num_instances, len(body_ids), 3, device=sim.device) @@ -997,7 +996,6 @@ def test_write_root_state(num_cubes, device, with_offset, state_location): env_idx = env_idx.to(device) for i in range(10): - # perform step sim.step() # update buffers diff --git a/source/isaaclab/test/assets/test_rigid_object_collection.py b/source/isaaclab/test/assets/test_rigid_object_collection.py index 3e75bf6c14a..ccce0e1bcb4 100644 --- a/source/isaaclab/test/assets/test_rigid_object_collection.py +++ b/source/isaaclab/test/assets/test_rigid_object_collection.py @@ -511,7 +511,7 @@ def test_object_state_properties(sim, num_envs, num_cubes, device, with_offset, torch.testing.assert_close(object_state_w[..., 3:7], object_link_state_w[..., 3:7]) # lin_vel will not match - # center of mass vel will be constant (i.e. spining around com) + # center of mass vel will be constant (i.e. spinning around com) torch.testing.assert_close( torch.zeros_like(object_com_state_w[..., 7:10]), object_com_state_w[..., 7:10], diff --git a/source/isaaclab/test/controllers/test_local_frame_task.py b/source/isaaclab/test/controllers/test_local_frame_task.py index eec4ed2ab61..c60db228a34 100644 --- a/source/isaaclab/test/controllers/test_local_frame_task.py +++ b/source/isaaclab/test/controllers/test_local_frame_task.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: BSD-3-Clause """Test cases for LocalFrameTask class.""" + # Import pinocchio in the main script to force the use of the dependencies installed by IsaacLab and not the one installed by Isaac Sim # pinocchio is required by the Pink IK controller import sys diff --git a/source/isaaclab/test/controllers/test_null_space_posture_task.py b/source/isaaclab/test/controllers/test_null_space_posture_task.py index 2d3be6159cd..cd972c67988 100644 --- a/source/isaaclab/test/controllers/test_null_space_posture_task.py +++ b/source/isaaclab/test/controllers/test_null_space_posture_task.py @@ -3,6 +3,7 @@ # # SPDX-License-Identifier: BSD-3-Clause """Launch Isaac Sim Simulator first.""" + # Import pinocchio in the main script to force the use of the dependencies installed by IsaacLab and not the one installed by Isaac Sim # pinocchio is required by the Pink IK controller import sys diff --git a/source/isaaclab/test/controllers/test_operational_space.py b/source/isaaclab/test/controllers/test_operational_space.py index 2533eaeeb59..eeec14d877d 100644 --- a/source/isaaclab/test/controllers/test_operational_space.py +++ b/source/isaaclab/test/controllers/test_operational_space.py @@ -198,7 +198,25 @@ def sim(): # Reference frame for targets frame = "root" - yield sim, num_envs, robot_cfg, ee_marker, goal_marker, contact_forces, target_abs_pos_set_b, target_abs_pose_set_b, target_rel_pos_set, target_rel_pose_set_b, target_abs_wrench_set, target_abs_pose_variable_kp_set, target_abs_pose_variable_set, target_hybrid_set_b, target_hybrid_variable_kp_set, target_hybrid_set_tilted, frame + yield ( + sim, + num_envs, + robot_cfg, + ee_marker, + goal_marker, + contact_forces, + target_abs_pos_set_b, + target_abs_pose_set_b, + target_rel_pos_set, + target_rel_pose_set_b, + target_abs_wrench_set, + target_abs_pose_variable_kp_set, + target_abs_pose_variable_set, + target_hybrid_set_b, + target_hybrid_variable_kp_set, + target_hybrid_set_tilted, + frame, + ) # Cleanup sim.stop() diff --git a/source/isaaclab/test/controllers/test_pink_ik.py b/source/isaaclab/test/controllers/test_pink_ik.py index e16e0a0f549..6cf3af6c2e7 100644 --- a/source/isaaclab/test/controllers/test_pink_ik.py +++ b/source/isaaclab/test/controllers/test_pink_ik.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: BSD-3-Clause """Launch Isaac Sim Simulator first.""" + # Import pinocchio in the main script to force the use of the dependencies installed by IsaacLab and not the one installed by Isaac Sim # pinocchio is required by the Pink IK controller import sys diff --git a/source/isaaclab/test/controllers/test_pink_ik_components.py b/source/isaaclab/test/controllers/test_pink_ik_components.py index 36bbea8ca31..7b06516724a 100644 --- a/source/isaaclab/test/controllers/test_pink_ik_components.py +++ b/source/isaaclab/test/controllers/test_pink_ik_components.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: BSD-3-Clause """Test cases for PinkKinematicsConfiguration class.""" + # Import pinocchio in the main script to force the use of the dependencies installed by IsaacLab and not the one installed by Isaac Sim # pinocchio is required by the Pink IK controller import sys diff --git a/source/isaaclab/test/managers/test_event_manager.py b/source/isaaclab/test/managers/test_event_manager.py index 64cba01564f..7a5aa0b652d 100644 --- a/source/isaaclab/test/managers/test_event_manager.py +++ b/source/isaaclab/test/managers/test_event_manager.py @@ -7,6 +7,7 @@ # pyright: reportPrivateUsage=none """Launch Isaac Sim Simulator first.""" + from collections.abc import Sequence from isaaclab.app import AppLauncher diff --git a/source/isaaclab/test/sensors/test_visuotactile_render.py b/source/isaaclab/test/sensors/test_visuotactile_render.py index b152ecc7497..2fb490033ae 100644 --- a/source/isaaclab/test/sensors/test_visuotactile_render.py +++ b/source/isaaclab/test/sensors/test_visuotactile_render.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: BSD-3-Clause """Tests for GelSight utility functions - primarily focused on GelsightRender.""" + """Launch Isaac Sim Simulator first.""" from isaaclab.app import AppLauncher diff --git a/source/isaaclab/test/utils/test_configclass.py b/source/isaaclab/test/utils/test_configclass.py index b37af093fa0..88fe192ef91 100644 --- a/source/isaaclab/test/utils/test_configclass.py +++ b/source/isaaclab/test/utils/test_configclass.py @@ -790,9 +790,9 @@ def test_functions_config(): """Tests having functions as values in the configuration instance.""" cfg = FunctionsDemoCfg() # check types - assert cfg.__annotations__["func"] == type(dummy_function1) - assert cfg.__annotations__["wrapped_func"] == type(wrapped_dummy_function3) - assert cfg.__annotations__["func_in_dict"] == dict + assert cfg.__annotations__["func"] is type(dummy_function1) + assert cfg.__annotations__["wrapped_func"] is type(wrapped_dummy_function3) + assert cfg.__annotations__["func_in_dict"] is dict # check calling assert cfg.func() == 1 assert cfg.wrapped_func() == 4 @@ -992,10 +992,10 @@ def test_config_with_class_type(): # since python 3.10, annotations are stored as strings annotations = {k: eval(v) if isinstance(v, str) else v for k, v in cfg.__annotations__.items()} # check types - assert annotations["class_name_1"] == type + assert annotations["class_name_1"] is type assert annotations["class_name_2"] == type[DummyClass] assert annotations["class_name_3"] == type[DummyClass] - assert annotations["class_name_4"] == ClassVar[type[DummyClass]] + assert annotations["class_name_4"] is ClassVar[type[DummyClass]] # check values assert cfg.class_name_1 == DummyClass assert cfg.class_name_2 == DummyClass diff --git a/source/isaaclab_assets/isaaclab_assets/robots/allegro.py b/source/isaaclab_assets/isaaclab_assets/robots/allegro.py index 7720d324a81..0e18ef77c13 100644 --- a/source/isaaclab_assets/isaaclab_assets/robots/allegro.py +++ b/source/isaaclab_assets/isaaclab_assets/robots/allegro.py @@ -15,7 +15,6 @@ """ - import math import isaaclab.sim as sim_utils diff --git a/source/isaaclab_assets/isaaclab_assets/robots/cart_double_pendulum.py b/source/isaaclab_assets/isaaclab_assets/robots/cart_double_pendulum.py index 6ab01086f6f..22028f39baf 100644 --- a/source/isaaclab_assets/isaaclab_assets/robots/cart_double_pendulum.py +++ b/source/isaaclab_assets/isaaclab_assets/robots/cart_double_pendulum.py @@ -5,7 +5,6 @@ """Configuration for a simple inverted Double Pendulum on a Cart robot.""" - import isaaclab.sim as sim_utils from isaaclab.actuators import ImplicitActuatorCfg from isaaclab.assets import ArticulationCfg diff --git a/source/isaaclab_assets/isaaclab_assets/robots/cartpole.py b/source/isaaclab_assets/isaaclab_assets/robots/cartpole.py index 7813c019534..1e236eda6b9 100644 --- a/source/isaaclab_assets/isaaclab_assets/robots/cartpole.py +++ b/source/isaaclab_assets/isaaclab_assets/robots/cartpole.py @@ -5,7 +5,6 @@ """Configuration for a simple Cartpole robot.""" - import isaaclab.sim as sim_utils from isaaclab.actuators import ImplicitActuatorCfg from isaaclab.assets import ArticulationCfg diff --git a/source/isaaclab_assets/isaaclab_assets/robots/franka.py b/source/isaaclab_assets/isaaclab_assets/robots/franka.py index 62d46338c18..caacf214c58 100644 --- a/source/isaaclab_assets/isaaclab_assets/robots/franka.py +++ b/source/isaaclab_assets/isaaclab_assets/robots/franka.py @@ -14,7 +14,6 @@ Reference: https://github.com/frankaemika/franka_ros """ - import isaaclab.sim as sim_utils from isaaclab.actuators import ImplicitActuatorCfg from isaaclab.assets.articulation import ArticulationCfg diff --git a/source/isaaclab_assets/isaaclab_assets/robots/shadow_hand.py b/source/isaaclab_assets/isaaclab_assets/robots/shadow_hand.py index 2e0bd54ee8f..d13e90e3b1c 100644 --- a/source/isaaclab_assets/isaaclab_assets/robots/shadow_hand.py +++ b/source/isaaclab_assets/isaaclab_assets/robots/shadow_hand.py @@ -15,7 +15,6 @@ """ - import isaaclab.sim as sim_utils from isaaclab.actuators import ImplicitActuatorCfg from isaaclab.assets.articulation import ArticulationCfg diff --git a/source/isaaclab_assets/isaaclab_assets/sensors/velodyne.py b/source/isaaclab_assets/isaaclab_assets/sensors/velodyne.py index 5ecfa42700e..6cd075f4fa2 100644 --- a/source/isaaclab_assets/isaaclab_assets/sensors/velodyne.py +++ b/source/isaaclab_assets/isaaclab_assets/sensors/velodyne.py @@ -5,7 +5,6 @@ """Configuration for Velodyne LiDAR sensors.""" - from isaaclab.sensors import RayCasterCfg, patterns ## diff --git a/source/isaaclab_mimic/isaaclab_mimic/datagen/data_generator.py b/source/isaaclab_mimic/isaaclab_mimic/datagen/data_generator.py index a6f85388424..a6f8b3cc017 100644 --- a/source/isaaclab_mimic/isaaclab_mimic/datagen/data_generator.py +++ b/source/isaaclab_mimic/isaaclab_mimic/datagen/data_generator.py @@ -6,6 +6,7 @@ """ Base class for data generator. """ + import asyncio import copy import logging @@ -187,10 +188,7 @@ def __repr__(self): Pretty print this object. """ msg = str(self.__class__.__name__) - msg += " (\n\tdataset_path={}\n\tdemo_keys={}\n)".format( - self.dataset_path, - self.demo_keys, - ) + msg += f" (\n\tdataset_path={self.dataset_path}\n\tdemo_keys={self.demo_keys}\n)" return msg def randomize_subtask_boundaries(self) -> dict[str, np.ndarray]: diff --git a/source/isaaclab_mimic/isaaclab_mimic/datagen/datagen_info.py b/source/isaaclab_mimic/isaaclab_mimic/datagen/datagen_info.py index 18036ea1cf5..e68d70ed952 100644 --- a/source/isaaclab_mimic/isaaclab_mimic/datagen/datagen_info.py +++ b/source/isaaclab_mimic/isaaclab_mimic/datagen/datagen_info.py @@ -6,6 +6,7 @@ """ Defines structure of information that is needed from an environment for data generation. """ + from copy import deepcopy diff --git a/source/isaaclab_mimic/isaaclab_mimic/datagen/generation.py b/source/isaaclab_mimic/isaaclab_mimic/datagen/generation.py index 784a563cd64..b1f45ab00b0 100644 --- a/source/isaaclab_mimic/isaaclab_mimic/datagen/generation.py +++ b/source/isaaclab_mimic/isaaclab_mimic/datagen/generation.py @@ -93,7 +93,6 @@ def env_loop( # simulate environment -- run everything in inference mode with contextlib.suppress(KeyboardInterrupt) and torch.inference_mode(): while True: - # check if any environment needs to be reset while waiting for actions while env_action_queue.qsize() != env.num_envs: asyncio_event_loop.run_until_complete(asyncio.sleep(0)) diff --git a/source/isaaclab_mimic/isaaclab_mimic/datagen/selection_strategy.py b/source/isaaclab_mimic/isaaclab_mimic/datagen/selection_strategy.py index 9028febbd42..dc773215b44 100644 --- a/source/isaaclab_mimic/isaaclab_mimic/datagen/selection_strategy.py +++ b/source/isaaclab_mimic/isaaclab_mimic/datagen/selection_strategy.py @@ -7,6 +7,7 @@ Selection strategies used by Isaac Lab Mimic to select subtask segments from source human demonstrations. """ + import abc # for abstract base class definitions import torch diff --git a/source/isaaclab_mimic/isaaclab_mimic/datagen/waypoint.py b/source/isaaclab_mimic/isaaclab_mimic/datagen/waypoint.py index 2996e616151..77b7447acff 100644 --- a/source/isaaclab_mimic/isaaclab_mimic/datagen/waypoint.py +++ b/source/isaaclab_mimic/isaaclab_mimic/datagen/waypoint.py @@ -6,6 +6,7 @@ """ A collection of classes used to represent waypoints and trajectories. """ + import asyncio import inspect import torch diff --git a/source/isaaclab_mimic/isaaclab_mimic/envs/franka_bin_stack_ik_rel_mimic_env_cfg.py b/source/isaaclab_mimic/isaaclab_mimic/envs/franka_bin_stack_ik_rel_mimic_env_cfg.py index fdc38c55b85..ca28719d730 100644 --- a/source/isaaclab_mimic/isaaclab_mimic/envs/franka_bin_stack_ik_rel_mimic_env_cfg.py +++ b/source/isaaclab_mimic/isaaclab_mimic/envs/franka_bin_stack_ik_rel_mimic_env_cfg.py @@ -16,7 +16,6 @@ class FrankaBinStackIKRelMimicEnvCfg(FrankaBinStackEnvCfg, MimicEnvCfg): """ def __post_init__(self): - # post init of parents super().__post_init__() diff --git a/source/isaaclab_tasks/isaaclab_tasks/direct/automate/factory_control.py b/source/isaaclab_tasks/isaaclab_tasks/direct/automate/factory_control.py index 58166eb9077..2bb44200654 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/direct/automate/factory_control.py +++ b/source/isaaclab_tasks/isaaclab_tasks/direct/automate/factory_control.py @@ -132,6 +132,8 @@ def get_pose_error( return pos_error, quat_error elif rot_error_type == "axis_angle": return pos_error, axis_angle_error + else: + raise ValueError(f"Unsupported rotation error type: {rot_error_type}. Valid: 'quat', 'axis_angle'.") def _get_delta_dof_pos(delta_pose, ik_method, jacobian, device): @@ -164,7 +166,7 @@ def _get_delta_dof_pos(delta_pose, ik_method, jacobian, device): U, S, Vh = torch.linalg.svd(jacobian) S_inv = 1.0 / S min_singular_value = 1.0e-5 - S_inv = torch.where(S > min_singular_value, S_inv, torch.zeros_like(S_inv)) + S_inv = torch.where(min_singular_value < S, S_inv, torch.zeros_like(S_inv)) jacobian_pinv = ( torch.transpose(Vh, dim0=1, dim1=2)[:, :, :6] @ torch.diag_embed(S_inv) @ torch.transpose(U, dim0=1, dim1=2) ) diff --git a/source/isaaclab_tasks/isaaclab_tasks/direct/automate/industreal_algo_utils.py b/source/isaaclab_tasks/isaaclab_tasks/direct/automate/industreal_algo_utils.py index 2527f9ef8ca..1efda7233ae 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/direct/automate/industreal_algo_utils.py +++ b/source/isaaclab_tasks/isaaclab_tasks/direct/automate/industreal_algo_utils.py @@ -105,7 +105,6 @@ def get_sdf_reward( sdf_reward = torch.zeros((num_envs,), dtype=torch.float32, device=device) for i in range(num_envs): - # Create copy of plug mesh mesh_points = wp.clone(wp_plug_mesh.points) mesh_indices = wp.clone(wp_plug_mesh.indices) diff --git a/source/isaaclab_tasks/isaaclab_tasks/direct/automate/soft_dtw_cuda.py b/source/isaaclab_tasks/isaaclab_tasks/direct/automate/soft_dtw_cuda.py index 12a4595654d..4a197de71c6 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/direct/automate/soft_dtw_cuda.py +++ b/source/isaaclab_tasks/isaaclab_tasks/direct/automate/soft_dtw_cuda.py @@ -52,7 +52,6 @@ def compute_softdtw_cuda(D, gamma, bandwidth, max_i, max_j, n_passes, R): # Go over each anti-diagonal. Only process threads that fall on the current on the anti-diagonal for p in range(n_passes): - # The index is actually 'p - tid' but need to force it in-bounds J = max(0, min(p - tid, max_j - 1)) @@ -61,7 +60,7 @@ def compute_softdtw_cuda(D, gamma, bandwidth, max_i, max_j, n_passes, R): j = J + 1 # Only compute if element[i, j] is on the current anti-diagonal, and also is within bounds - if tid + J == p and (tid < max_i and J < max_j): + if tid + J == p and (tid < max_i and max_j > J): # Don't compute if outside bandwidth if not (abs(i - j) > bandwidth > 0): r0 = -R[b, i - 1, j - 1] * inv_gamma @@ -96,8 +95,7 @@ def compute_softdtw_backward_cuda(D, R, inv_gamma, bandwidth, max_i, max_j, n_pa j = J + 1 # Only compute if element[i, j] is on the current anti-diagonal, and also is within bounds - if tid + J == rev_p and (tid < max_i and J < max_j): - + if tid + J == rev_p and (tid < max_i and max_j > J): if math.isinf(R[k, i, j]): R[k, i, j] = -math.inf @@ -199,7 +197,6 @@ def compute_softdtw(D, gamma, bandwidth): for b in prange(B): for j in range(1, M + 1): for i in range(1, N + 1): - # Check the pruning condition if 0 < bandwidth < np.abs(i - j): continue @@ -230,7 +227,6 @@ def compute_softdtw_backward(D_, R, gamma, bandwidth): for k in prange(B): for j in range(M, 0, -1): for i in range(N, 0, -1): - if np.isinf(R[k, i, j]): R[k, i, j] = -np.inf @@ -403,9 +399,8 @@ def profile(batch_size, seq_len_a, seq_len_b, dims, tol_backward): n_iters = 6 print( - "Profiling forward() + backward() times for batch_size={}, seq_len_a={}, seq_len_b={}, dims={}...".format( - batch_size, seq_len_a, seq_len_b, dims - ) + f"Profiling forward() + backward() times for batch_size={batch_size}, seq_len_a={seq_len_a}," + f" seq_len_b={seq_len_b}, dims={dims}..." ) times_cpu = [] @@ -444,7 +439,6 @@ def profile(batch_size, seq_len_a, seq_len_b, dims, tol_backward): # ---------------------------------------------------------------------------------------------------------------------- if __name__ == "__main__": - torch.manual_seed(1234) profile(128, 17, 15, 2, tol_backward=1e-6) diff --git a/source/isaaclab_tasks/isaaclab_tasks/direct/cartpole_showcase/cartpole/cartpole_env.py b/source/isaaclab_tasks/isaaclab_tasks/direct/cartpole_showcase/cartpole/cartpole_env.py index 4fed9a1d8d5..dc03eb299d0 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/direct/cartpole_showcase/cartpole/cartpole_env.py +++ b/source/isaaclab_tasks/isaaclab_tasks/direct/cartpole_showcase/cartpole/cartpole_env.py @@ -42,7 +42,6 @@ def _apply_action(self) -> None: self.cartpole.set_joint_effort_target(target, joint_ids=self._cart_dof_idx) def _get_observations(self) -> dict: - # fundamental spaces # - Box if isinstance(self.single_observation_space["policy"], gym.spaces.Box): diff --git a/source/isaaclab_tasks/isaaclab_tasks/direct/factory/factory_control.py b/source/isaaclab_tasks/isaaclab_tasks/direct/factory/factory_control.py index 6714f0d5b23..664c53b77cc 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/direct/factory/factory_control.py +++ b/source/isaaclab_tasks/isaaclab_tasks/direct/factory/factory_control.py @@ -142,6 +142,8 @@ def get_pose_error( return pos_error, quat_error elif rot_error_type == "axis_angle": return pos_error, axis_angle_error + else: + raise ValueError(f"Unsupported rotation error type: {rot_error_type}. Valid: 'quat', 'axis_angle'.") def get_delta_dof_pos(delta_pose, ik_method, jacobian, device): @@ -174,7 +176,7 @@ def get_delta_dof_pos(delta_pose, ik_method, jacobian, device): U, S, Vh = torch.linalg.svd(jacobian) S_inv = 1.0 / S min_singular_value = 1.0e-5 - S_inv = torch.where(S > min_singular_value, S_inv, torch.zeros_like(S_inv)) + S_inv = torch.where(min_singular_value < S, S_inv, torch.zeros_like(S_inv)) jacobian_pinv = ( torch.transpose(Vh, dim0=1, dim1=2)[:, :, :6] @ torch.diag_embed(S_inv) @ torch.transpose(U, dim0=1, dim1=2) ) diff --git a/source/isaaclab_tasks/isaaclab_tasks/direct/humanoid_amp/motions/motion_loader.py b/source/isaaclab_tasks/isaaclab_tasks/direct/humanoid_amp/motions/motion_loader.py index 1ae9ea6ecf4..756f6c61604 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/direct/humanoid_amp/motions/motion_loader.py +++ b/source/isaaclab_tasks/isaaclab_tasks/direct/humanoid_amp/motions/motion_loader.py @@ -3,10 +3,11 @@ # # SPDX-License-Identifier: BSD-3-Clause +from __future__ import annotations + import numpy as np import os import torch -from typing import Optional class MotionLoader: @@ -71,10 +72,10 @@ def _interpolate( self, a: torch.Tensor, *, - b: Optional[torch.Tensor] = None, - blend: Optional[torch.Tensor] = None, - start: Optional[np.ndarray] = None, - end: Optional[np.ndarray] = None, + b: torch.Tensor | None = None, + blend: torch.Tensor | None = None, + start: np.ndarray | None = None, + end: np.ndarray | None = None, ) -> torch.Tensor: """Linear interpolation between consecutive values. @@ -102,10 +103,10 @@ def _slerp( self, q0: torch.Tensor, *, - q1: Optional[torch.Tensor] = None, - blend: Optional[torch.Tensor] = None, - start: Optional[np.ndarray] = None, - end: Optional[np.ndarray] = None, + q1: torch.Tensor | None = None, + blend: torch.Tensor | None = None, + start: np.ndarray | None = None, + end: np.ndarray | None = None, ) -> torch.Tensor: """Interpolation between consecutive rotations (Spherical Linear Interpolation). @@ -196,7 +197,7 @@ def sample_times(self, num_samples: int, duration: float | None = None) -> np.nd return duration * np.random.uniform(low=0.0, high=1.0, size=num_samples) def sample( - self, num_samples: int, times: Optional[np.ndarray] = None, duration: float | None = None + self, num_samples: int, times: np.ndarray | None = None, duration: float | None = None ) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor]: """Sample motion data. diff --git a/source/isaaclab_tasks/isaaclab_tasks/direct/humanoid_amp/motions/motion_viewer.py b/source/isaaclab_tasks/isaaclab_tasks/direct/humanoid_amp/motions/motion_viewer.py index e9981a94823..55125715b4b 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/direct/humanoid_amp/motions/motion_viewer.py +++ b/source/isaaclab_tasks/isaaclab_tasks/direct/humanoid_amp/motions/motion_viewer.py @@ -2,6 +2,7 @@ # All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause + from __future__ import annotations import matplotlib diff --git a/source/isaaclab_tasks/isaaclab_tasks/manager_based/classic/humanoid/agents/rsl_rl_ppo_cfg.py b/source/isaaclab_tasks/isaaclab_tasks/manager_based/classic/humanoid/agents/rsl_rl_ppo_cfg.py index 5da79221b5b..f2c7f48e455 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/manager_based/classic/humanoid/agents/rsl_rl_ppo_cfg.py +++ b/source/isaaclab_tasks/isaaclab_tasks/manager_based/classic/humanoid/agents/rsl_rl_ppo_cfg.py @@ -13,7 +13,6 @@ ==================================================================================================== """ - from isaaclab.utils import configclass from isaaclab_rl.rsl_rl import RslRlOnPolicyRunnerCfg, RslRlPpoActorCriticCfg, RslRlPpoAlgorithmCfg diff --git a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/deploy/mdp/events.py b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/deploy/mdp/events.py index 048e7ca3f76..c8355ccc9d1 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/deploy/mdp/events.py +++ b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/deploy/mdp/events.py @@ -5,7 +5,6 @@ """Class-based event terms specific to the gear assembly manipulation environments.""" - from __future__ import annotations import random diff --git a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/inhand/mdp/events.py b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/inhand/mdp/events.py index 2b75a1501cc..59dbca4bf97 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/inhand/mdp/events.py +++ b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/inhand/mdp/events.py @@ -5,7 +5,6 @@ """Functions specific to the in-hand dexterous manipulation environments.""" - from __future__ import annotations import torch diff --git a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/place/mdp/observations.py b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/place/mdp/observations.py index faf90330568..e0c89017e81 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/place/mdp/observations.py +++ b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/place/mdp/observations.py @@ -41,7 +41,7 @@ def object_poses_in_base_frame( return pos_object_base elif return_key == "quat": return quat_object_base - elif return_key is None: + else: return torch.cat((pos_object_base, quat_object_base), dim=1) diff --git a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/galbot/stack_joint_pos_env_cfg.py b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/galbot/stack_joint_pos_env_cfg.py index 57a438e4d6b..b0662275043 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/galbot/stack_joint_pos_env_cfg.py +++ b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/galbot/stack_joint_pos_env_cfg.py @@ -277,11 +277,9 @@ def __post_init__(self): # post init of parent super().__post_init__() - l, r = self.events.randomize_cube_positions.params["pose_range"]["y"] - self.events.randomize_cube_positions.params["pose_range"]["y"] = ( - -r, - -l, - ) # move to area below right hand + # Move to area below right hand (invert y-axis) + left, right = self.events.randomize_cube_positions.params["pose_range"]["y"] + self.events.randomize_cube_positions.params["pose_range"]["y"] = (-right, -left) # Set actions for the specific robot type (galbot) self.actions.arm_action = mdp.JointPositionActionCfg( diff --git a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/mdp/observations.py b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/mdp/observations.py index ef46bae7d3c..bb8dfd3aa58 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/mdp/observations.py +++ b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/mdp/observations.py @@ -434,7 +434,7 @@ def cube_poses_in_base_frame( return pos_cubes_base elif return_key == "quat": return quat_cubes_base - elif return_key is None: + else: return torch.cat((pos_cubes_base, quat_cubes_base), dim=1) @@ -528,5 +528,5 @@ def ee_frame_pose_in_base_frame( return ee_pos_in_base elif return_key == "quat": return ee_quat_in_base - elif return_key is None: + else: return torch.cat((ee_pos_in_base, ee_quat_in_base), dim=1) diff --git a/source/isaaclab_tasks/isaaclab_tasks/utils/hydra.py b/source/isaaclab_tasks/isaaclab_tasks/utils/hydra.py index d7aa7674bd4..525b425917f 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/utils/hydra.py +++ b/source/isaaclab_tasks/isaaclab_tasks/utils/hydra.py @@ -5,7 +5,6 @@ """Sub-module with utilities for the hydra configuration system.""" - import functools from collections.abc import Callable diff --git a/source/isaaclab_tasks/isaaclab_tasks/utils/importer.py b/source/isaaclab_tasks/isaaclab_tasks/utils/importer.py index bb4bb398029..ddbab7ede41 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/utils/importer.py +++ b/source/isaaclab_tasks/isaaclab_tasks/utils/importer.py @@ -60,13 +60,16 @@ def _walk_packages( ``pkgutil.walk_packages`` function for more details. """ + # Default blacklist if blacklist_pkgs is None: blacklist_pkgs = [] - def seen(p, m={}): + def seen(p: str, m: dict[str, bool] = {}) -> bool: + """Check if a package has been seen before.""" if p in m: return True - m[p] = True # noqa: R503 + m[p] = True + return False for info in pkgutil.iter_modules(path, prefix): # check blacklisted @@ -85,7 +88,7 @@ def seen(p, m={}): else: raise else: - path = getattr(sys.modules[info.name], "__path__", None) or [] + path: list = getattr(sys.modules[info.name], "__path__", []) # don't traverse path items we've seen before path = [p for p in path if not seen(p)] diff --git a/source/isaaclab_tasks/test/benchmarking/conftest.py b/source/isaaclab_tasks/test/benchmarking/conftest.py index 20ddad8b548..e4ef86d7dfd 100644 --- a/source/isaaclab_tasks/test/benchmarking/conftest.py +++ b/source/isaaclab_tasks/test/benchmarking/conftest.py @@ -6,7 +6,8 @@ import json import pytest -import env_benchmark_test_utils as utils +# Local imports should be imported last +import env_benchmark_test_utils as utils # isort: skip # Global variable for storing KPI data GLOBAL_KPI_STORE = {} diff --git a/source/isaaclab_tasks/test/test_environments.py b/source/isaaclab_tasks/test/test_environments.py index 3f0b9536825..1b6d17f6aa7 100644 --- a/source/isaaclab_tasks/test/test_environments.py +++ b/source/isaaclab_tasks/test/test_environments.py @@ -23,10 +23,11 @@ import pytest -from env_test_utils import _run_environments, setup_environment - import isaaclab_tasks # noqa: F401 +# Local imports should be imported last +from env_test_utils import _run_environments, setup_environment # isort: skip + @pytest.mark.parametrize("num_envs, device", [(32, "cuda"), (1, "cuda")]) @pytest.mark.parametrize("task_name", setup_environment(include_play=False, factory_envs=False, multi_agent=False)) diff --git a/source/isaaclab_tasks/test/test_environments_with_stage_in_memory.py b/source/isaaclab_tasks/test/test_environments_with_stage_in_memory.py index b10ca715ff0..8e1eadab4ec 100644 --- a/source/isaaclab_tasks/test/test_environments_with_stage_in_memory.py +++ b/source/isaaclab_tasks/test/test_environments_with_stage_in_memory.py @@ -24,10 +24,12 @@ import pytest -from env_test_utils import _run_environments, setup_environment - import isaaclab_tasks # noqa: F401 +# Local imports should be imported last +from env_test_utils import _run_environments, setup_environment # isort: skip + + # note, running an env test without stage in memory then # running an env test with stage in memory causes IsaacLab to hang. # so, here we run all envs with stage in memory separately diff --git a/source/isaaclab_tasks/test/test_factory_environments.py b/source/isaaclab_tasks/test/test_factory_environments.py index d29208b63b7..05908000655 100644 --- a/source/isaaclab_tasks/test/test_factory_environments.py +++ b/source/isaaclab_tasks/test/test_factory_environments.py @@ -15,10 +15,11 @@ import pytest -from env_test_utils import _check_random_actions, setup_environment - import isaaclab_tasks # noqa: F401 +# Local imports should be imported last +from env_test_utils import _check_random_actions, setup_environment # isort: skip + @pytest.mark.parametrize("num_envs, device", [(32, "cuda"), (1, "cuda")]) @pytest.mark.parametrize("task_name", setup_environment(factory_envs=True, multi_agent=False)) diff --git a/source/isaaclab_tasks/test/test_lift_teddy_bear.py b/source/isaaclab_tasks/test/test_lift_teddy_bear.py index d60b16b7244..b0d28c93fc5 100644 --- a/source/isaaclab_tasks/test/test_lift_teddy_bear.py +++ b/source/isaaclab_tasks/test/test_lift_teddy_bear.py @@ -24,10 +24,11 @@ import pytest -from env_test_utils import _run_environments - import isaaclab_tasks # noqa: F401 +# Local imports should be imported last +from env_test_utils import _run_environments # isort: skip + @pytest.mark.parametrize("num_envs, device", [(32, "cuda"), (1, "cuda")]) def test_lift_teddy_bear_environment(num_envs, device): diff --git a/source/isaaclab_tasks/test/test_multi_agent_environments.py b/source/isaaclab_tasks/test/test_multi_agent_environments.py index 0d72c3427e6..478cb3942e1 100644 --- a/source/isaaclab_tasks/test/test_multi_agent_environments.py +++ b/source/isaaclab_tasks/test/test_multi_agent_environments.py @@ -16,10 +16,11 @@ import pytest -from env_test_utils import _check_random_actions, setup_environment - import isaaclab_tasks # noqa: F401 +# Local imports should be imported last +from env_test_utils import _check_random_actions, setup_environment # isort: skip + @pytest.mark.parametrize("num_envs, device", [(32, "cuda"), (1, "cuda")]) @pytest.mark.parametrize("task_name", setup_environment(multi_agent=True)) diff --git a/source/isaaclab_tasks/test/test_record_video.py b/source/isaaclab_tasks/test/test_record_video.py index 9a6d95e303a..e50c90093cd 100644 --- a/source/isaaclab_tasks/test/test_record_video.py +++ b/source/isaaclab_tasks/test/test_record_video.py @@ -20,11 +20,12 @@ import omni.usd -from env_test_utils import setup_environment - import isaaclab_tasks # noqa: F401 from isaaclab_tasks.utils import parse_env_cfg +# Local imports should be imported last +from env_test_utils import setup_environment # isort: skip + @pytest.fixture(scope="function") def setup_video_params(): diff --git a/tools/conftest.py b/tools/conftest.py index de835f5a465..f8646ce02e9 100644 --- a/tools/conftest.py +++ b/tools/conftest.py @@ -144,11 +144,7 @@ def run_individual_tests(test_files, workspace_root, isaacsim_ci): env = os.environ.copy() # Determine timeout for this test - timeout = ( - test_settings.PER_TEST_TIMEOUTS[file_name] - if file_name in test_settings.PER_TEST_TIMEOUTS - else test_settings.DEFAULT_TIMEOUT - ) + timeout = test_settings.PER_TEST_TIMEOUTS.get(file_name, test_settings.DEFAULT_TIMEOUT) # Prepare command # Note: Command options matter as they are used for cleanups inside AppLauncher diff --git a/tools/template/cli.py b/tools/template/cli.py index 6150631e555..d922025e070 100644 --- a/tools/template/cli.py +++ b/tools/template/cli.py @@ -73,7 +73,7 @@ def input_checkbox(self, message: str, choices: list[str], default: str | None = def transformer(result: list[str]) -> str: if "all" in result or "both" in result: token = "all" if "all" in result else "both" - return f'{token} ({", ".join(choices[:choices.index("---")])})' + return f"{token} ({', '.join(choices[: choices.index('---')])})" return ", ".join(result) return inquirer.checkbox( diff --git a/tools/template/generator.py b/tools/template/generator.py index 633e4c0f418..493fcf991b6 100644 --- a/tools/template/generator.py +++ b/tools/template/generator.py @@ -96,22 +96,22 @@ def _generate_task_per_workflow(task_dir: str, specification: dict) -> None: # workflow-specific content if task_spec["workflow"]["name"] == "direct": # - task/*env_cfg.py - template = jinja_env.get_template(f'tasks/direct_{task_spec["workflow"]["type"]}/env_cfg') + template = jinja_env.get_template(f"tasks/direct_{task_spec['workflow']['type']}/env_cfg") _write_file( - os.path.join(task_dir, f'{task_spec["filename"]}_env_cfg.py'), content=template.render(**specification) + os.path.join(task_dir, f"{task_spec['filename']}_env_cfg.py"), content=template.render(**specification) ) # - task/*env.py - template = jinja_env.get_template(f'tasks/direct_{task_spec["workflow"]["type"]}/env') - _write_file(os.path.join(task_dir, f'{task_spec["filename"]}_env.py'), content=template.render(**specification)) + template = jinja_env.get_template(f"tasks/direct_{task_spec['workflow']['type']}/env") + _write_file(os.path.join(task_dir, f"{task_spec['filename']}_env.py"), content=template.render(**specification)) elif task_spec["workflow"]["name"] == "manager-based": # - task/*env_cfg.py - template = jinja_env.get_template(f'tasks/manager-based_{task_spec["workflow"]["type"]}/env_cfg') + template = jinja_env.get_template(f"tasks/manager-based_{task_spec['workflow']['type']}/env_cfg") _write_file( - os.path.join(task_dir, f'{task_spec["filename"]}_env_cfg.py'), content=template.render(**specification) + os.path.join(task_dir, f"{task_spec['filename']}_env_cfg.py"), content=template.render(**specification) ) # - task/mdp folder shutil.copytree( - os.path.join(TEMPLATE_DIR, "tasks", f'manager-based_{task_spec["workflow"]["type"]}', "mdp"), + os.path.join(TEMPLATE_DIR, "tasks", f"manager-based_{task_spec['workflow']['type']}", "mdp"), os.path.join(task_dir, "mdp"), dirs_exist_ok=True, ) diff --git a/tools/template/templates/external/.vscode/tools/settings.template.json b/tools/template/templates/external/.vscode/tools/settings.template.json index 99dc714bb2c..716897355e6 100644 --- a/tools/template/templates/external/.vscode/tools/settings.template.json +++ b/tools/template/templates/external/.vscode/tools/settings.template.json @@ -56,10 +56,9 @@ // This enables python language server. Seems to work slightly better than jedi: "python.languageServer": "Pylance", // We use "black" as a formatter: - "black-formatter.args": ["--line-length", "120"], - // Use flake8 for linting - "flake8.enabled": true, - "flake8.args": ["--config", "${workspaceFolder}/pyproject.toml"], + "black-formatter.args": ["--line-length", "120", "--unstable"], + // Use ruff as a linter + "ruff.configuration": "${workspaceFolder}/pyproject.toml", // Use docstring generator "autoDocstring.docstringFormat": "google", "autoDocstring.guessTypes": true,