From d43fc78a77bf0dc72219d10df49b927258eebdd8 Mon Sep 17 00:00:00 2001 From: Mohammed Yasin <32206511+Y-T-G@users.noreply.github.com> Date: Sun, 22 Dec 2024 08:24:40 +0800 Subject: [PATCH] Validate arguments passed as dict to `settings.update()` (#18337) Signed-off-by: Glenn Jocher Co-authored-by: UltralyticsAssistant Co-authored-by: Glenn Jocher --- ultralytics/utils/__init__.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/ultralytics/utils/__init__.py b/ultralytics/utils/__init__.py index f02e148b..126c823a 100644 --- a/ultralytics/utils/__init__.py +++ b/ultralytics/utils/__init__.py @@ -12,12 +12,12 @@ import subprocess import sys import threading import time -import urllib import uuid from pathlib import Path from threading import Lock from types import SimpleNamespace from typing import Union +from urllib.parse import unquote import cv2 import matplotlib.pyplot as plt @@ -1130,7 +1130,8 @@ class JSONDict(dict): def __str__(self): """Return a pretty-printed JSON string representation of the dictionary.""" - return f'JSONDict("{self.file_path}"):\n{json.dumps(dict(self), indent=2, ensure_ascii=False, default=self._json_default)}' + contents = json.dumps(dict(self), indent=2, ensure_ascii=False, default=self._json_default) + return f'JSONDict("{self.file_path}"):\n{contents}' def update(self, *args, **kwargs): """Update the dictionary and persist changes.""" @@ -1238,14 +1239,23 @@ class SettingsManager(JSONDict): f"Please change one to avoid possible issues during training. {self.help_msg}" ) + def __setitem__(self, key, value): + """Updates one key: value pair.""" + self.update({key: value}) + def update(self, *args, **kwargs): """Updates settings, validating keys and types.""" + for arg in args: + if isinstance(arg, dict): + kwargs.update(arg) for k, v in kwargs.items(): if k not in self.defaults: raise KeyError(f"No Ultralytics setting '{k}'. {self.help_msg}") t = type(self.defaults[k]) if not isinstance(v, t): - raise TypeError(f"Ultralytics setting '{k}' must be of type '{t}', not '{type(v)}'. {self.help_msg}") + raise TypeError( + f"Ultralytics setting '{k}' must be '{t.__name__}' type, not '{type(v).__name__}'. {self.help_msg}" + ) super().update(*args, **kwargs) def reset(self): @@ -1265,7 +1275,7 @@ def deprecation_warn(arg, new_arg=None): def clean_url(url): """Strip auth from URL, i.e. https://url.com/file.txt?auth -> https://url.com/file.txt.""" url = Path(url).as_posix().replace(":/", "://") # Pathlib turns :// -> :/, as_posix() for Windows - return urllib.parse.unquote(url).split("?")[0] # '%2F' to '/', split https://url.com/file.txt?auth + return unquote(url).split("?")[0] # '%2F' to '/', split https://url.com/file.txt?auth def url2file(url):