From cc5818bdaf3818d2e4fcd15e9ede9550b1d1e7ac Mon Sep 17 00:00:00 2001 From: Tiexin Guo Date: Thu, 11 Apr 2024 08:56:53 +0800 Subject: [PATCH] refactor: update ruff to 0.3.5 latest version (#1179) Update ruff to the latest version, 0.3.5. --- ops/charm.py | 7 ++++--- ops/framework.py | 17 ++++++++-------- ops/model.py | 50 +++++++++++++++++++++++++----------------------- ops/testing.py | 8 +++++--- pyproject.toml | 6 ++++++ tox.ini | 2 +- 6 files changed, 50 insertions(+), 40 deletions(-) diff --git a/ops/charm.py b/ops/charm.py index 073ccf8fd..aeb97c79c 100644 --- a/ops/charm.py +++ b/ops/charm.py @@ -673,9 +673,10 @@ def restore(self, snapshot: Dict[str, Any]): (s for s in storages if s.index == storage_index), None) # type: ignore if self.storage is None: - msg = 'failed loading storage (name={!r}, index={!r}) from snapshot' \ - .format(storage_name, storage_index) - raise RuntimeError(msg) + raise RuntimeError( + f'failed loading storage (name={storage_name!r}, ' + f'index={storage_index!r}) from snapshot' + ) if storage_location is None: raise RuntimeError( 'failed loading storage location from snapshot.' diff --git a/ops/framework.py b/ops/framework.py index 23b982c7b..5ca8674d4 100644 --- a/ops/framework.py +++ b/ops/framework.py @@ -315,11 +315,9 @@ class BoundEvent: """Event bound to an Object.""" def __repr__(self): - return ''.format( - self.event_type.__name__, - type(self.emitter).__name__, - self.event_kind, - hex(id(self)), + return ( + f'' ) def __init__(self, emitter: 'Object', @@ -1106,8 +1104,8 @@ def __setattr__(self, key: str, value: Any): if not isinstance(unwrapped, (type(None), int, float, str, bytes, list, dict, set)): raise AttributeError( - 'attribute {!r} cannot be a {}: must be int/float/dict/list/etc'.format( - key, type(unwrapped).__name__)) + f'attribute {key!r} cannot be a {type(unwrapped).__name__}: ' + 'must be int/float/dict/list/etc') self._data[key] = unwrapped @@ -1191,8 +1189,9 @@ def __get__(self, if bound is not None: # the StoredState instance is being stored in two different # attributes -> unclear what is expected of us -> bail out - raise RuntimeError("StoredState shared by {0}.{1} and {0}.{2}".format( - cls.__name__, self.attr_name, attr_name)) + raise RuntimeError( + f'StoredState shared by {cls.__name__}.{self.attr_name} and ' + f'{cls.__name__}.{attr_name}') # we've found ourselves for the first time; save where, and bind the object self.attr_name = attr_name self.parent_type = cls diff --git a/ops/model.py b/ops/model.py index 7ca4e1381..3a3d42317 100644 --- a/ops/model.py +++ b/ops/model.py @@ -588,8 +588,8 @@ def set_workload_version(self, version: str) -> None: shown in the output of 'juju status'. """ if not isinstance(version, str): - raise TypeError("workload version must be a str, not {}: {!r}".format( - type(version).__name__, version)) + raise TypeError( + f'workload version must be a str, not {type(version).__name__}: {version!r}') self._backend.application_version_set(version) @property @@ -862,9 +862,9 @@ def _invalidate(self, relation_name: str): def _get_unique(self, relation_name: str, relation_id: Optional[int] = None): if relation_id is not None: if not isinstance(relation_id, int): - raise ModelError('relation id {} must be int or None not {}'.format( - relation_id, - type(relation_id).__name__)) + raise ModelError( + f'relation id {relation_id} must be int or None, ' + f'not {type(relation_id).__name__}') for relation in self[relation_name]: if relation.id == relation_id: return relation @@ -908,8 +908,9 @@ def get(self, binding_key: Union[str, 'Relation']) -> 'Binding': binding_name = binding_key relation_id = None else: - raise ModelError('binding key must be str or relation instance, not {}' - ''.format(type(binding_key).__name__)) + raise ModelError( + f'binding key must be str or relation instance, not {type(binding_key).__name__}' + ) binding = self._data.get(binding_key) if binding is None: binding = Binding(binding_name, relation_id, self._backend) @@ -1629,9 +1630,8 @@ def _validate_read(self): if self._backend.app_name == self._entity.name: # minions can't read local app databags raise RelationDataAccessError( - "{} is not leader and cannot read its own application databag".format( - self._backend.unit_name - ) + f'{self._backend.unit_name} is not leader and cannot read its own ' + f'application databag' ) return True @@ -1660,9 +1660,8 @@ def _validate_write(self, key: str, value: str): is_our_app: bool = self._backend.app_name == self._entity.name if not is_our_app: raise RelationDataAccessError( - "{} cannot write the data of remote application {}".format( - self._backend.app_name, self._entity.name - )) + f'{self._backend.app_name} cannot write the data of remote application ' + f'{self._entity.name}') # Whether the application data bag is mutable or not depends on # whether this unit is a leader or not, but this is not guaranteed # to be always true during the same hook execution. @@ -1676,9 +1675,8 @@ def _validate_write(self, key: str, value: str): # is it OUR UNIT's? if self._backend.unit_name != self._entity.name: raise RelationDataAccessError( - "{} cannot write databag of {}: not the same unit.".format( - self._backend.unit_name, self._entity.name - ) + f'{self._backend.unit_name} cannot write databag of {self._entity.name}: ' + f'not the same unit.' ) def __setitem__(self, key: str, value: str): @@ -2867,8 +2865,9 @@ class TooManyRelatedAppsError(ModelError): """Raised by :meth:`Model.get_relation` if there is more than one integrated application.""" def __init__(self, relation_name: str, num_related: int, max_supported: int): - super().__init__('Too many remote applications on {} ({} > {})'.format( - relation_name, num_related, max_supported)) + super().__init__( + f'Too many remote applications on {relation_name} ({num_related} > {max_supported})' + ) self.relation_name = relation_name self.num_related = num_related self.max_supported = max_supported @@ -2950,8 +2949,9 @@ def _format_action_result_dict(input: Dict[str, Any], # other exceptions raised on key validation... raise ValueError(f'invalid key {key!r}; must be a string') if not _ACTION_RESULT_KEY_REGEX.match(key): - raise ValueError("key '{!r}' is invalid: must be similar to 'key', 'some-key2', or " - "'some.key'".format(key)) + raise ValueError( + f"key {key!r} is invalid: must be similar to 'key', 'some-key2', " + f"or 'some.key'") if parent_key: key = f"{parent_key}.{key}" @@ -2960,8 +2960,9 @@ def _format_action_result_dict(input: Dict[str, Any], value = typing.cast(Dict[str, Any], value) output_ = _format_action_result_dict(value, key, output_) elif key in output_: - raise ValueError("duplicate key detected in dictionary passed to 'action-set': {!r}" - .format(key)) + raise ValueError( + f"duplicate key detected in dictionary passed to 'action-set': {key!r}" + ) else: output_[key] = value # type: ignore @@ -3531,8 +3532,9 @@ def validate_metric_key(cls, key: str): def validate_metric_label(cls, label_name: str): if cls.METRIC_KEY_REGEX.match(label_name) is None: raise ModelError( - 'invalid metric label name {!r}: must match {}'.format( - label_name, cls.METRIC_KEY_REGEX.pattern)) + f'invalid metric label name {label_name!r}: ' + f'must match {cls.METRIC_KEY_REGEX.pattern}' + ) @classmethod def format_metric_value(cls, value: Union[int, float]): diff --git a/ops/testing.py b/ops/testing.py index d33ecc4ff..6af417978 100644 --- a/ops/testing.py +++ b/ops/testing.py @@ -990,9 +990,11 @@ def add_relation_unit(self, relation_id: int, remote_unit_name: str) -> None: app = relation.app if not remote_unit_name.startswith(app.name): warnings.warn( - 'Remote unit name invalid: the remote application of {} is called {!r}; ' - 'the remote unit name should be {}/, not {!r}.' - ''.format(relation_name, app.name, app.name, remote_unit_name)) + f'Remote unit name invalid: ' + f'the remote application of {relation_name} is called {app.name!r}; ' + f'the remote unit name should be {app.name}/, ' + f'not {remote_unit_name!r}.' + ) app_and_units = self._backend._relation_app_and_units app_and_units[relation_id]["units"].append(remote_unit_name) # Make sure that the Model reloads the relation_list for this relation_id, as well as diff --git a/pyproject.toml b/pyproject.toml index 6cf8c8ae8..f873965c0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -119,6 +119,8 @@ ignore = [ # No explicit `stacklevel` keyword argument found "B028", + # Return condition directly, prefer readability. + "SIM103", # Use contextlib.suppress() instead of try/except: pass "SIM105", # Use a single `with` statement with multiple contexts instead of nested `with` statements @@ -170,6 +172,10 @@ ignore = [ "RUF001", # String contains ambiguous `µ` (MICRO SIGN). Did you mean `μ` (GREEK SMALL LETTER MU)? "RUF002", # Docstring contains ambiguous `µ` (MICRO SIGN). Did you mean `μ` (GREEK SMALL LETTER MU)? ] +"test/test_helpers.py" = [ + "S605", # Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell` + "S607", # Starting a process with a partial executable path +] [tool.ruff.lint.pydocstyle] convention = "google" diff --git a/tox.ini b/tox.ini index 504542475..933b7b2eb 100644 --- a/tox.ini +++ b/tox.ini @@ -49,7 +49,7 @@ commands = [testenv:lint] description = Check code against coding style standards deps = - ruff~=0.2.2 + ruff~=0.3.5 commands = ruff check --preview