[Security] Add Bandit (#795)
This commit is contained in:
parent
9c1a893ee3
commit
8861546ad8
|
@ -2,6 +2,7 @@ exclude: ^(tests/data)
|
||||||
default_language_version:
|
default_language_version:
|
||||||
python: python3.10
|
python: python3.10
|
||||||
repos:
|
repos:
|
||||||
|
##### Style / Misc. #####
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v5.0.0
|
rev: v5.0.0
|
||||||
hooks:
|
hooks:
|
||||||
|
@ -14,7 +15,7 @@ repos:
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
- repo: https://github.com/crate-ci/typos
|
- repo: https://github.com/crate-ci/typos
|
||||||
rev: v1.29.10
|
rev: v1.30.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: typos
|
- id: typos
|
||||||
args: [--force-exclude]
|
args: [--force-exclude]
|
||||||
|
@ -23,16 +24,24 @@ repos:
|
||||||
hooks:
|
hooks:
|
||||||
- id: pyupgrade
|
- id: pyupgrade
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
rev: v0.9.6
|
rev: v0.9.9
|
||||||
hooks:
|
hooks:
|
||||||
- id: ruff
|
- id: ruff
|
||||||
args: [--fix]
|
args: [--fix]
|
||||||
- id: ruff-format
|
- id: ruff-format
|
||||||
|
|
||||||
|
##### Security #####
|
||||||
- repo: https://github.com/gitleaks/gitleaks
|
- repo: https://github.com/gitleaks/gitleaks
|
||||||
rev: v8.23.3
|
rev: v8.24.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: gitleaks
|
- id: gitleaks
|
||||||
- repo: https://github.com/woodruffw/zizmor-pre-commit
|
- repo: https://github.com/woodruffw/zizmor-pre-commit
|
||||||
rev: v1.3.1
|
rev: v1.4.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: zizmor
|
- id: zizmor
|
||||||
|
- repo: https://github.com/PyCQA/bandit
|
||||||
|
rev: 1.8.3
|
||||||
|
hooks:
|
||||||
|
- id: bandit
|
||||||
|
args: ["-c", "pyproject.toml"]
|
||||||
|
additional_dependencies: ["bandit[toml]"]
|
||||||
|
|
|
@ -17,6 +17,7 @@ import logging
|
||||||
import os
|
import os
|
||||||
import os.path as osp
|
import os.path as osp
|
||||||
import platform
|
import platform
|
||||||
|
import subprocess
|
||||||
from copy import copy
|
from copy import copy
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
@ -165,23 +166,31 @@ def capture_timestamp_utc():
|
||||||
|
|
||||||
|
|
||||||
def say(text, blocking=False):
|
def say(text, blocking=False):
|
||||||
# Check if mac, linux, or windows.
|
system = platform.system()
|
||||||
if platform.system() == "Darwin":
|
|
||||||
cmd = f'say "{text}"'
|
|
||||||
if not blocking:
|
|
||||||
cmd += " &"
|
|
||||||
elif platform.system() == "Linux":
|
|
||||||
cmd = f'spd-say "{text}"'
|
|
||||||
if blocking:
|
|
||||||
cmd += " --wait"
|
|
||||||
elif platform.system() == "Windows":
|
|
||||||
# TODO(rcadene): Make blocking option work for Windows
|
|
||||||
cmd = (
|
|
||||||
'PowerShell -Command "Add-Type -AssemblyName System.Speech; '
|
|
||||||
f"(New-Object System.Speech.Synthesis.SpeechSynthesizer).Speak('{text}')\""
|
|
||||||
)
|
|
||||||
|
|
||||||
os.system(cmd)
|
if system == "Darwin":
|
||||||
|
cmd = ["say", text]
|
||||||
|
|
||||||
|
elif system == "Linux":
|
||||||
|
cmd = ["spd-say", text]
|
||||||
|
if blocking:
|
||||||
|
cmd.append("--wait")
|
||||||
|
|
||||||
|
elif system == "Windows":
|
||||||
|
cmd = [
|
||||||
|
"PowerShell",
|
||||||
|
"-Command",
|
||||||
|
"Add-Type -AssemblyName System.Speech; "
|
||||||
|
f"(New-Object System.Speech.Synthesis.SpeechSynthesizer).Speak('{text}')",
|
||||||
|
]
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise RuntimeError("Unsupported operating system for text-to-speech.")
|
||||||
|
|
||||||
|
if blocking:
|
||||||
|
subprocess.run(cmd, check=True)
|
||||||
|
else:
|
||||||
|
subprocess.Popen(cmd, creationflags=subprocess.CREATE_NO_WINDOW if system == "Windows" else 0)
|
||||||
|
|
||||||
|
|
||||||
def log_say(text, play_sounds, blocking=False):
|
def log_say(text, play_sounds, blocking=False):
|
||||||
|
|
|
@ -454,7 +454,7 @@ def _compile_episode_data(
|
||||||
|
|
||||||
|
|
||||||
@parser.wrap()
|
@parser.wrap()
|
||||||
def eval(cfg: EvalPipelineConfig):
|
def eval_main(cfg: EvalPipelineConfig):
|
||||||
logging.info(pformat(asdict(cfg)))
|
logging.info(pformat(asdict(cfg)))
|
||||||
|
|
||||||
# Check device is available
|
# Check device is available
|
||||||
|
@ -499,4 +499,4 @@ def eval(cfg: EvalPipelineConfig):
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
init_logging()
|
init_logging()
|
||||||
eval()
|
eval_main()
|
||||||
|
|
|
@ -194,7 +194,7 @@ def run_server(
|
||||||
]
|
]
|
||||||
|
|
||||||
response = requests.get(
|
response = requests.get(
|
||||||
f"https://huggingface.co/datasets/{repo_id}/resolve/main/meta/episodes.jsonl"
|
f"https://huggingface.co/datasets/{repo_id}/resolve/main/meta/episodes.jsonl", timeout=5
|
||||||
)
|
)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
# Split into lines and parse each line as JSON
|
# Split into lines and parse each line as JSON
|
||||||
|
@ -318,7 +318,9 @@ def get_episode_language_instruction(dataset: LeRobotDataset, ep_index: int) ->
|
||||||
|
|
||||||
|
|
||||||
def get_dataset_info(repo_id: str) -> IterableNamespace:
|
def get_dataset_info(repo_id: str) -> IterableNamespace:
|
||||||
response = requests.get(f"https://huggingface.co/datasets/{repo_id}/resolve/main/meta/info.json")
|
response = requests.get(
|
||||||
|
f"https://huggingface.co/datasets/{repo_id}/resolve/main/meta/info.json", timeout=5
|
||||||
|
)
|
||||||
response.raise_for_status() # Raises an HTTPError for bad responses
|
response.raise_for_status() # Raises an HTTPError for bad responses
|
||||||
dataset_info = response.json()
|
dataset_info = response.json()
|
||||||
dataset_info["repo_id"] = repo_id
|
dataset_info["repo_id"] = repo_id
|
||||||
|
|
|
@ -42,22 +42,22 @@
|
||||||
<ul>
|
<ul>
|
||||||
<template x-for="episode in paginatedEpisodes" :key="episode">
|
<template x-for="episode in paginatedEpisodes" :key="episode">
|
||||||
<li class="font-mono text-sm mt-0.5">
|
<li class="font-mono text-sm mt-0.5">
|
||||||
<a :href="'episode_' + episode"
|
<a :href="'episode_' + episode"
|
||||||
:class="{'underline': true, 'font-bold -ml-1': episode == {{ episode_id }}}"
|
:class="{'underline': true, 'font-bold -ml-1': episode == {{ episode_id }}}"
|
||||||
x-text="'Episode ' + episode"></a>
|
x-text="'Episode ' + episode"></a>
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="flex items-center mt-3 text-xs" x-show="totalPages > 1">
|
<div class="flex items-center mt-3 text-xs" x-show="totalPages > 1">
|
||||||
<button @click="prevPage()"
|
<button @click="prevPage()"
|
||||||
class="px-2 py-1 bg-slate-800 rounded mr-2"
|
class="px-2 py-1 bg-slate-800 rounded mr-2"
|
||||||
:class="{'opacity-50 cursor-not-allowed': page === 1}"
|
:class="{'opacity-50 cursor-not-allowed': page === 1}"
|
||||||
:disabled="page === 1">
|
:disabled="page === 1">
|
||||||
« Prev
|
« Prev
|
||||||
</button>
|
</button>
|
||||||
<span class="font-mono mr-2" x-text="` ${page} / ${totalPages}`"></span>
|
<span class="font-mono mr-2" x-text="` ${page} / ${totalPages}`"></span>
|
||||||
<button @click="nextPage()"
|
<button @click="nextPage()"
|
||||||
class="px-2 py-1 bg-slate-800 rounded"
|
class="px-2 py-1 bg-slate-800 rounded"
|
||||||
:class="{'opacity-50 cursor-not-allowed': page === totalPages}"
|
:class="{'opacity-50 cursor-not-allowed': page === totalPages}"
|
||||||
:disabled="page === totalPages">
|
:disabled="page === totalPages">
|
||||||
|
@ -65,10 +65,10 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- episodes menu for small screens -->
|
<!-- episodes menu for small screens -->
|
||||||
<div class="flex overflow-x-auto md:hidden" x-data="episodePagination">
|
<div class="flex overflow-x-auto md:hidden" x-data="episodePagination">
|
||||||
<button @click="prevPage()"
|
<button @click="prevPage()"
|
||||||
class="px-2 bg-slate-800 rounded mr-2"
|
class="px-2 bg-slate-800 rounded mr-2"
|
||||||
:class="{'opacity-50 cursor-not-allowed': page === 1}"
|
:class="{'opacity-50 cursor-not-allowed': page === 1}"
|
||||||
:disabled="page === 1">«</button>
|
:disabled="page === 1">«</button>
|
||||||
|
@ -83,7 +83,7 @@
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<button @click="nextPage()"
|
<button @click="nextPage()"
|
||||||
class="px-2 bg-slate-800 rounded ml-2"
|
class="px-2 bg-slate-800 rounded ml-2"
|
||||||
:class="{'opacity-50 cursor-not-allowed': page === totalPages}"
|
:class="{'opacity-50 cursor-not-allowed': page === totalPages}"
|
||||||
:disabled="page === totalPages">» </button>
|
:disabled="page === totalPages">» </button>
|
||||||
|
@ -476,7 +476,7 @@
|
||||||
episodes: {{ episodes }},
|
episodes: {{ episodes }},
|
||||||
pageSize: 100,
|
pageSize: 100,
|
||||||
page: 1,
|
page: 1,
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
// Find which page contains the current episode_id
|
// Find which page contains the current episode_id
|
||||||
const currentEpisodeId = {{ episode_id }};
|
const currentEpisodeId = {{ episode_id }};
|
||||||
|
@ -485,23 +485,23 @@
|
||||||
this.page = Math.floor(episodeIndex / this.pageSize) + 1;
|
this.page = Math.floor(episodeIndex / this.pageSize) + 1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
get totalPages() {
|
get totalPages() {
|
||||||
return Math.ceil(this.episodes.length / this.pageSize);
|
return Math.ceil(this.episodes.length / this.pageSize);
|
||||||
},
|
},
|
||||||
|
|
||||||
get paginatedEpisodes() {
|
get paginatedEpisodes() {
|
||||||
const start = (this.page - 1) * this.pageSize;
|
const start = (this.page - 1) * this.pageSize;
|
||||||
const end = start + this.pageSize;
|
const end = start + this.pageSize;
|
||||||
return this.episodes.slice(start, end);
|
return this.episodes.slice(start, end);
|
||||||
},
|
},
|
||||||
|
|
||||||
nextPage() {
|
nextPage() {
|
||||||
if (this.page < this.totalPages) {
|
if (this.page < this.totalPages) {
|
||||||
this.page++;
|
this.page++;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
prevPage() {
|
prevPage() {
|
||||||
if (this.page > 1) {
|
if (this.page > 1) {
|
||||||
this.page--;
|
this.page--;
|
||||||
|
@ -515,7 +515,7 @@
|
||||||
window.addEventListener('keydown', (e) => {
|
window.addEventListener('keydown', (e) => {
|
||||||
// Use the space bar to play and pause, instead of default action (e.g. scrolling)
|
// Use the space bar to play and pause, instead of default action (e.g. scrolling)
|
||||||
const { keyCode, key } = e;
|
const { keyCode, key } = e;
|
||||||
|
|
||||||
if (keyCode === 32 || key === ' ') {
|
if (keyCode === 32 || key === ' ') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const btnPause = document.querySelector('[x-ref="btnPause"]');
|
const btnPause = document.querySelector('[x-ref="btnPause"]');
|
||||||
|
|
|
@ -111,10 +111,19 @@ exclude = [
|
||||||
"venv",
|
"venv",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
[tool.ruff.lint]
|
[tool.ruff.lint]
|
||||||
select = ["E4", "E7", "E9", "F", "I", "N", "B", "C4", "SIM"]
|
select = ["E4", "E7", "E9", "F", "I", "N", "B", "C4", "SIM"]
|
||||||
|
|
||||||
|
[tool.bandit]
|
||||||
|
exclude_dirs = [
|
||||||
|
"tests",
|
||||||
|
"benchmarks",
|
||||||
|
"lerobot/common/datasets/push_dataset_to_hub",
|
||||||
|
"lerobot/common/datasets/v2/convert_dataset_v1_to_v2",
|
||||||
|
"lerobot/common/policies/pi0/conversion_scripts",
|
||||||
|
"lerobot/scripts/push_dataset_to_hub.py",
|
||||||
|
]
|
||||||
|
skips = ["B101", "B311", "B404", "B603"]
|
||||||
|
|
||||||
[tool.typos]
|
[tool.typos]
|
||||||
default.extend-ignore-re = [
|
default.extend-ignore-re = [
|
||||||
|
|
Loading…
Reference in New Issue