From 657b9caf7c22d3c0e82ca9a9ad9b50e4cc3ec0fb Mon Sep 17 00:00:00 2001 From: Shahmir Varqha Date: Fri, 28 Aug 2026 15:46:45 +0800 Subject: [PATCH 1/2] chore(ruff): enable dictionary comprehension check --- marimo/_runtime/commands.py | 9 +++++---- marimo/_runtime/reload/module_watcher.py | 9 +++++---- marimo/_runtime/utils/set_ui_element_request_manager.py | 3 +-- marimo/_session/state/session_view.py | 9 +++++---- pyproject.toml | 1 - 5 files changed, 16 insertions(+), 15 deletions(-) diff --git a/marimo/_runtime/commands.py b/marimo/_runtime/commands.py index 3c610c59fd2..b21abd3f08d 100644 --- a/marimo/_runtime/commands.py +++ b/marimo/_runtime/commands.py @@ -182,10 +182,11 @@ def _url_to_dict(url: URL) -> dict[str, Encodable]: query_params[k].append(str(v)) # Convert headers to dict, remove all marimo-specific headers - headers: dict[str, str] = {} - for k, v in request.headers.items(): - if not k.startswith(("marimo", "x-marimo")): - headers[k] = v + headers: dict[str, str] = { + k: v + for k, v in request.headers.items() + if not k.startswith(("marimo", "x-marimo")) + } return HTTPRequest( url=url_dict, diff --git a/marimo/_runtime/reload/module_watcher.py b/marimo/_runtime/reload/module_watcher.py index 6d7a50c60a2..339d007066f 100644 --- a/marimo/_runtime/reload/module_watcher.py +++ b/marimo/_runtime/reload/module_watcher.py @@ -125,7 +125,6 @@ def _check_modules( sys_modules: dict[str, types.ModuleType], ) -> dict[str, types.ModuleType]: """Returns the set of modules used by the graph that have been modified""" - stale_modules: dict[str, types.ModuleType] = {} modified_modules = reloader.check(modules=sys_modules, reload=False) # TODO(akshayka): could also exclude modules part of the standard library; # haven't found a reliable way to do this, however. @@ -136,15 +135,17 @@ def _check_modules( t.__file__ for t in target_modules if hasattr(t, "__file__") } - for modname, module in modules.items(): + stale_modules: dict[str, types.ModuleType] = { + modname: module + for modname, module in modules.items() if _depends_on( src_module=module, target_modules=target_modules, target_filenames=target_filenames, excludes=excludes, reloader=reloader, - ): - stale_modules[modname] = module + ) + } return stale_modules diff --git a/marimo/_runtime/utils/set_ui_element_request_manager.py b/marimo/_runtime/utils/set_ui_element_request_manager.py index 5bee5f2d334..22be65ed95c 100644 --- a/marimo/_runtime/utils/set_ui_element_request_manager.py +++ b/marimo/_runtime/utils/set_ui_element_request_manager.py @@ -83,8 +83,7 @@ def _merge_ui_commands( merged: dict[UIElementId, Any] = {} last_cmd = cmds[-1] for cmd in cmds: - for ui_id, value in cmd.ids_and_values: - merged[ui_id] = value + merged.update(cmd.ids_and_values) return [ UpdateUIElementCommand( diff --git a/marimo/_session/state/session_view.py b/marimo/_session/state/session_view.py index 62b46eb7b93..0d3d84da475 100644 --- a/marimo/_session/state/session_view.py +++ b/marimo/_session/state/session_view.py @@ -305,10 +305,11 @@ def add_notification(self, notification: NotificationMessage) -> None: } # Remove any variable values that are no longer in scope. - next_values: dict[str, VariableValue] = {} - for name, value in self.variable_values.items(): - if name in variable_names: - next_values[name] = value + next_values: dict[str, VariableValue] = { + name: value + for name, value in self.variable_values.items() + if name in variable_names + } self.variable_values = next_values # Remove any table values that are no longer in scope. diff --git a/pyproject.toml b/pyproject.toml index bfd4ca1ea63..947d4a6dbed 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -350,7 +350,6 @@ ignore = [ "TC006", # Add quotes to type expression in typing.cast() "PERF203", # try-except within a loop incurs performance overhead; not always possible "PERF401", # Use {message_str} to create a transformed list; at the cost of readability - "PERF403", # Use a dictionary comprehension instead of a for-loop; at the cost of readability # TODO: we should fix these, and enable this rule "PT011", # `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception "E501", # Line too long, we still trim From 78907a887bde4d5f817d7ec1395583fb7736a54d Mon Sep 17 00:00:00 2001 From: Shahmir Varqha Date: Fri, 28 Aug 2026 20:20:11 +0800 Subject: [PATCH 2/2] chore(ruff): enable dictionary items check --- marimo/_ast/app_config.py | 8 ++++---- marimo/_lint/rules/breaking/graph.py | 8 ++++---- marimo/_runtime/executor/lifecycles/strict.py | 4 ++-- marimo/_runtime/utils/set_ui_element_request_manager.py | 4 ++-- marimo/_server/ai/prompts.py | 8 +++----- marimo/_utils/deep_merge.py | 8 ++++---- pyproject.toml | 1 - 7 files changed, 19 insertions(+), 22 deletions(-) diff --git a/marimo/_ast/app_config.py b/marimo/_ast/app_config.py index fc056901013..d87af29a65c 100644 --- a/marimo/_ast/app_config.py +++ b/marimo/_ast/app_config.py @@ -56,9 +56,9 @@ def from_untrusted_dict( # internal) other_allowed = {"_filename"} config = _AppConfig() - for key in updates: + for key, value in updates.items(): if hasattr(config, key): - config.__setattr__(key, updates[key]) + config.__setattr__(key, value) elif key not in other_allowed and not silent: LOGGER.warning( f"Unrecognized key '{key}' in app config. Ignoring." @@ -73,9 +73,9 @@ def asdict(self) -> dict[str, Any]: def update(self, updates: dict[str, Any]) -> _AppConfig: config_dict = asdict(self) - for key in updates: + for key, value in updates.items(): if key in config_dict: - self.__setattr__(key, updates[key]) + self.__setattr__(key, value) return self diff --git a/marimo/_lint/rules/breaking/graph.py b/marimo/_lint/rules/breaking/graph.py index 3541d6f3c1e..26d12539acf 100644 --- a/marimo/_lint/rules/breaking/graph.py +++ b/marimo/_lint/rules/breaking/graph.py @@ -209,10 +209,10 @@ async def _validate_graph( _ErrorInfo(cell_id=cell_id, line=line, column=column) ) - for name in names: - lines = [info.line for info in names[name]] - columns = [info.column for info in names[name]] - cell_ids = [info.cell_id for info in names[name]] + for name, infos in names.items(): + lines = [info.line for info in infos] + columns = [info.column for info in infos] + cell_ids = [info.cell_id for info in infos] diagnostic = Diagnostic( message=f"Variable '{name}' is defined in multiple cells", diff --git a/marimo/_runtime/executor/lifecycles/strict.py b/marimo/_runtime/executor/lifecycles/strict.py index 383fe9ce3f3..13abdb22be0 100644 --- a/marimo/_runtime/executor/lifecycles/strict.py +++ b/marimo/_runtime/executor/lifecycles/strict.py @@ -169,6 +169,6 @@ def teardown( del glbls[df] # Repopulate this cell's private variables. - for df in lcls: + for df, value in lcls.items(): if is_mangled_local(df, cell.cell_id): - glbls[df] = lcls[df] + glbls[df] = value diff --git a/marimo/_runtime/utils/set_ui_element_request_manager.py b/marimo/_runtime/utils/set_ui_element_request_manager.py index 22be65ed95c..64756167ee9 100644 --- a/marimo/_runtime/utils/set_ui_element_request_manager.py +++ b/marimo/_runtime/utils/set_ui_element_request_manager.py @@ -135,14 +135,14 @@ def _merge_model_commands( ): model_buffers[mid][tuple(path)] = buf - for mid in model_state: + for mid, state in model_state.items(): paths = list(model_buffers[mid].keys()) bufs = list(model_buffers[mid].values()) result.append( ModelCommand( model_id=mid, message=ModelUpdateMessage( - state=model_state[mid], + state=state, buffer_paths=[list(p) for p in paths], ), buffers=bufs, diff --git a/marimo/_server/ai/prompts.py b/marimo/_server/ai/prompts.py index 582858f9db3..9b5c8511e2c 100644 --- a/marimo/_server/ai/prompts.py +++ b/marimo/_server/ai/prompts.py @@ -276,12 +276,10 @@ def _get_session_info(session_id: SessionId) -> str: def _single_cell_language_rules() -> str: """Per-language rules for chat modes that emit one cell at a time.""" out = "" - for language in language_rules: - if not language_rules[language]: + for language, rules in language_rules.items(): + if not rules: continue - out += ( - f"\n\n## Rules for {language}:\n{_rules(language_rules[language])}" - ) + out += f"\n\n## Rules for {language}:\n{_rules(rules)}" return out diff --git a/marimo/_utils/deep_merge.py b/marimo/_utils/deep_merge.py index 8e0d4fd52a9..670dfe76459 100644 --- a/marimo/_utils/deep_merge.py +++ b/marimo/_utils/deep_merge.py @@ -49,16 +49,16 @@ def _merge_replace( - Editing a record preserves unmodified fields (values are merged) """ result = {} - for key in update: + for key, update_value in update.items(): if ( key in original and isinstance(original[key], dict) - and isinstance(update[key], dict) + and isinstance(update_value, dict) ): # Merge the record's fields (original first, update overwrites) - result[key] = {**original[key], **update[key]} + result[key] = {**original[key], **update_value} else: - result[key] = update[key] + result[key] = update_value return result diff --git a/pyproject.toml b/pyproject.toml index 947d4a6dbed..fa3f1a45f45 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -369,7 +369,6 @@ ignore = [ "S102", # Use of `exec` "PYI036", # Bad `sys.exit` annotation "DTZ005", # `datetime.now()` called without `tzinfo` - "PLC0206", # Dict index without `.items()` "SIM115", # Open file without context handler "DTZ006", # `datetime.fromtimestamp()` called without `tzinfo` "DTZ007", # `datetime.strptime()` called without zone