Skip to content

refactor: centralize placeholder substitution logic into shared/functions.py#1186

Open
Ow0cast wants to merge 1 commit intoallthingslinux:mainfrom
Ow0cast:main
Open

refactor: centralize placeholder substitution logic into shared/functions.py#1186
Ow0cast wants to merge 1 commit intoallthingslinux:mainfrom
Ow0cast:main

Conversation

@Ow0cast
Copy link
Contributor

@Ow0cast Ow0cast commented Feb 3, 2026

Pull Request

Description

pretty much a copy paste move of substitute_placeholders from plugins/atl/fact.py to shared/functions.py

If your PR is related to an issue, please include the issue number below:

Related Issue: N/A

Type of Change:

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Performance improvement
  • Code refactoring
  • Test improvements

Guidelines

  • My code follows the style guidelines of this project (formatted with Ruff)

  • I have performed a self-review of my own code

  • I have commented my code, particularly in hard-to-understand areas

  • I have made corresponding changes to the documentation if needed

  • My changes generate no new warnings

  • I have tested this change

  • Any dependent changes have been merged and published in downstream modules

  • I have added all appropriate labels to this PR

  • I have followed all of these guidelines.

How Has This Been Tested? (if applicable)

all modified tests pass

Screenshots (if applicable)

Please add screenshots to help explain your changes.

Additional Information

Please add any other information that is important to this PR.

@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Feb 3, 2026

Reviewer's Guide

Centralizes the placeholder substitution logic into a shared utility function and updates all callers (facts plugin, activity handler, and performance tests) to use the new shared implementation.

Class diagram for shared substitute_placeholders utility

classDiagram
    class Tux {
    }

    class Fact {
        +Tux bot
        +dict facts_data
        +_fetch_fact(fact_type str) tuple
        +fact_type_autocomplete(interaction AppCommandInteraction, current str) Coroutine
        +fact(ctx Context, fact_type str) Coroutine
    }

    class ActivityHandler {
        +Tux bot
        +_create_activity_with_substitution(activity Activity) Activity
        +build_activity_list() list
    }

    class Functions {
        +substitute_placeholders(bot Tux, text str) str
    }

    Fact --> Tux : has
    ActivityHandler --> Tux : has

    Fact ..> Functions : uses substitute_placeholders
    ActivityHandler ..> Functions : uses substitute_placeholders
Loading

File-Level Changes

Change Details Files
Move placeholder substitution logic into shared utility and expose as substitute_placeholders.
  • Added substitute_placeholders(bot, text) to tux.shared.functions with existing placeholder behavior for member_count, guild_count, bot_name, bot_version, and prefix.
  • Imported CONFIG and get_version, and guarded Tux import with TYPE_CHECKING to avoid runtime dependency cycles.
  • Exported substitute_placeholders via all in tux.shared.functions.
src/tux/shared/functions.py
Refactor facts plugin to use shared substitute_placeholders instead of its private implementation.
  • Removed local _substitute_placeholders implementation from the Fact plugin.
  • Replaced all calls to _substitute_placeholders with substitute_placeholders(self.bot, ...).
  • Adjusted imports to pull substitute_placeholders from tux.shared.functions instead of CONFIG/get_version directly.
src/tux/plugins/atl/fact.py
Refactor activity handler to use shared substitute_placeholders instead of its method.
  • Removed ActivityHandler._substitute_placeholders method and its associated CONFIG/get_version usage.
  • Updated _create_activity_with_substitution to call substitute_placeholders(self.bot, activity.name).
  • Imported substitute_placeholders from tux.shared.functions.
src/tux/services/handlers/activity.py
Update performance tests to target the shared substitute_placeholders function.
  • Changed imports in performance tests to use tux.shared.functions.substitute_placeholders instead of the plugin-local helper.
  • Kept benchmark structure the same to validate performance characteristics of the new shared implementation.
tests/performance/test_string_performance.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@gemini-code-assist
Copy link

Summary of Changes

Hello @Ow0cast, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly refactors the codebase by centralizing the placeholder substitution logic into a dedicated shared utility module. This change eliminates duplicate code, enhances maintainability, and promotes better organization by providing a single, consistent function for handling text placeholder replacements across different parts of the application.

Highlights

  • Centralized Placeholder Logic: The _substitute_placeholders function has been moved from src/tux/plugins/atl/fact.py and src/tux/services/handlers/activity.py to src/tux/shared/functions.py.
  • Function Renaming: The moved function has been renamed to substitute_placeholders (removing the leading underscore) to signify its new public and shared utility status.
  • Updated Call Sites: All previous calls to the local _substitute_placeholders function/method in fact.py and activity.py have been updated to use the newly centralized substitute_placeholders function.
  • Import Adjustments: Relevant import statements in fact.py, activity.py, and functions.py have been modified to reflect the new module structure.
  • Test Updates: Performance tests in tests/performance/test_string_performance.py have been updated to import and call the function from its new shared location.
Changelog
  • src/tux/plugins/atl/fact.py
    • Removed the contextlib import.
    • Removed the local _substitute_placeholders function definition.
    • Updated imports to remove tux.shared.config and tux.shared.version, and added tux.shared.functions.substitute_placeholders.
    • Replaced all occurrences of _substitute_placeholders with substitute_placeholders.
  • src/tux/services/handlers/activity.py
    • Removed the local _substitute_placeholders method from the ActivityHandler class.
    • Updated imports to remove tux.shared.version and added tux.shared.functions.substitute_placeholders.
    • Replaced calls to self._substitute_placeholders with substitute_placeholders(self.bot, ...).
  • src/tux/shared/functions.py
    • Added contextlib, TYPE_CHECKING, Tux, CONFIG, and get_version imports.
    • Added the substitute_placeholders function, including its comprehensive docstring and type hints.
    • Included substitute_placeholders in the __all__ list for explicit export.
  • tests/performance/test_string_performance.py
    • Modified the import statement for _substitute_placeholders to from tux.shared.functions import substitute_placeholders.
    • Updated calls to the function from _substitute_placeholders to substitute_placeholders.
Activity
  • The pull request was initiated by Ow0cast.
  • The author explicitly states the change is a "copy paste move" for refactoring, indicating a clear intent to centralize code.
  • The PR includes self-review and confirmation that all modified tests pass, suggesting a thorough check of the changes.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link

coderabbitai bot commented Feb 3, 2026

📝 Walkthrough

Walkthrough

This change centralizes placeholder substitution logic by introducing a new public utility function substitute_placeholders in src/tux/shared/functions.py. The function is integrated across fact plugins, activity handlers, and tests, replacing previous inline implementations with consistent references to the shared utility.

Changes

Cohort / File(s) Summary
Centralized Placeholder Substitution
src/tux/shared/functions.py
Added new public utility function substitute_placeholders(bot, text) that handles one-pass substitution for member count, guild count, bot name, bot version, and prefix placeholders. Introduced required imports (contextlib, CONFIG, get_version) and added function to __all__ for public API exposure.
Plugin and Handler Integration
src/tux/plugins/atl/fact.py, src/tux/services/handlers/activity.py
Removed internal _substitute_placeholders methods and replaced all call sites with calls to the new centralized substitute_placeholders function. Updated imports to use the shared utility instead of local implementations.
Test Updates
tests/performance/test_string_performance.py
Updated import path from tux.plugins.atl.fact._substitute_placeholders to tux.shared.functions.substitute_placeholders and adjusted corresponding function calls to match the new public API.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: centralizing placeholder substitution logic into shared/functions.py, which aligns with the changeset moving substitute_placeholders across multiple files.
Description check ✅ Passed The description is directly related to the changeset, explaining that it's a copy-paste move of substitute_placeholders from plugins/atl/fact.py to shared/functions.py, which matches the actual changes.
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

🧹 Recent nitpick comments
src/tux/shared/functions.py (1)

467-490: Consider narrowing the exception suppression scope.

Using contextlib.suppress(Exception) silently swallows all errors including potential programming bugs (e.g., AttributeError if bot.guilds is unexpectedly None, or issues with CONFIG/get_version). While the safe fallback of returning original text is reasonable, this makes debugging difficult when things go wrong.

Consider either:

  1. Suppressing only expected exceptions (e.g., KeyError, AttributeError)
  2. Adding a logged warning on exception to aid debugging
♻️ Optional: Add logging for suppressed exceptions
-    with contextlib.suppress(Exception):
+    try:
         # Build placeholder map only for placeholders present in text
         placeholders: dict[str, str] = {}
         # ... rest of logic ...
         if placeholders:
             text = text.format_map(placeholders)
+    except Exception:
+        logger.debug(f"Placeholder substitution failed for text: {text[:50]!r}...")
     return text
📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cfa8ccf and f6e4b79.

📒 Files selected for processing (4)
  • src/tux/plugins/atl/fact.py
  • src/tux/services/handlers/activity.py
  • src/tux/shared/functions.py
  • tests/performance/test_string_performance.py
🧰 Additional context used
📓 Path-based instructions (6)
**/*.py

📄 CodeRabbit inference engine (.cursor/rules/rules.mdc)

**/*.py: Follow Python code style guide and best practices as defined in core/style-guide.mdc
Follow error handling patterns as defined in error-handling/patterns.mdc
Follow loguru logging patterns as defined in error-handling/logging.mdc
Follow Sentry integration patterns as defined in error-handling/sentry.mdc

**/*.py: Use strict type hints with Type | None instead of Optional[Type] in Python
Use NumPy docstrings for documenting functions and classes in Python
Use absolute imports preferred, relative imports allowed within the same module in Python
Group imports in order: stdlib → third-party → local with blank lines between groups in Python
Maintain 88 character line length in Python code
Use snake_case for functions and variables, PascalCase for classes, UPPER_CASE for constants in Python
Add imports to the top of the file in Python unless absolutely necessary
Use async/await for all I/O operations including database and HTTP requests in Python
Use Pydantic for data validation in Python
Log errors with context information in Python
Validate all user input at boundaries in Python code
Keep individual Python files to a maximum of 1600 lines
Use Ruff for code formatting and linting in Python
Use basedpyright for type checking in Python

Files:

  • src/tux/plugins/atl/fact.py
  • src/tux/shared/functions.py
  • tests/performance/test_string_performance.py
  • src/tux/services/handlers/activity.py
src/tux/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

src/tux/**/*.py: Use custom exceptions for business logic error handling in Python
Add complete type hints for all public APIs in Python
Add docstrings for all public APIs in Python

Files:

  • src/tux/plugins/atl/fact.py
  • src/tux/shared/functions.py
  • src/tux/services/handlers/activity.py
**/tests/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/rules.mdc)

**/tests/**/*.py: Follow fixture usage patterns as defined in testing/fixtures.mdc
Follow test marker conventions as defined in testing/markers.mdc
Follow async testing patterns as defined in testing/async.mdc
Follow test quality philosophy, behavior-driven testing, and ACT pattern as defined in testing/test-quality.mdc

Files:

  • tests/performance/test_string_performance.py
tests/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Use pytest with markers (unit, integration, slow, database, async) for testing Python code

Files:

  • tests/performance/test_string_performance.py
**/services/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/rules.mdc)

Follow DatabaseService patterns as defined in database/services.mdc

Files:

  • src/tux/services/handlers/activity.py
src/tux/services/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Implement services with dependency injection, keeping them stateless where possible

Files:

  • src/tux/services/handlers/activity.py
🧠 Learnings (2)
📚 Learning: 2026-01-29T20:04:43.675Z
Learnt from: CR
Repo: allthingslinux/tux PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-29T20:04:43.675Z
Learning: Applies to src/tux/**/*.py : Add docstrings for all public APIs in Python

Applied to files:

  • src/tux/shared/functions.py
📚 Learning: 2026-01-29T20:04:43.675Z
Learnt from: CR
Repo: allthingslinux/tux PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-29T20:04:43.675Z
Learning: Applies to src/tux/**/*.py : Add complete type hints for all public APIs in Python

Applied to files:

  • src/tux/shared/functions.py
🧬 Code graph analysis (3)
src/tux/plugins/atl/fact.py (1)
src/tux/shared/functions.py (1)
  • substitute_placeholders (445-490)
tests/performance/test_string_performance.py (1)
src/tux/shared/functions.py (1)
  • substitute_placeholders (445-490)
src/tux/services/handlers/activity.py (1)
src/tux/shared/functions.py (1)
  • substitute_placeholders (445-490)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Seer Code Review
  • GitHub Check: Run All Tests (3.13.11)
  • GitHub Check: cubic · AI code reviewer
🔇 Additional comments (13)
src/tux/shared/functions.py (3)

9-21: LGTM on imports and type checking setup.

The new imports and TYPE_CHECKING block are correctly structured for the centralized utility function.


33-33: LGTM on public API export.

Correctly added to __all__ for explicit public API exposure.


445-466: Well-documented public API.

The function has complete type hints and a comprehensive NumPy-style docstring listing all available placeholders. Based on learnings: "Add docstrings for all public APIs in Python" and "Add complete type hints for all public APIs in Python".

tests/performance/test_string_performance.py (3)

13-13: LGTM on import update.

Correctly updated to use the centralized public API instead of the previous internal helper.


23-42: LGTM on test update.

The test correctly uses the new centralized substitute_placeholders function with the same call signature and mock setup.


44-62: LGTM on second test update.

Consistent with the first test - correctly updated to use the centralized function.

src/tux/services/handlers/activity.py (2)

17-17: LGTM on import update.

Correctly imports the centralized substitute_placeholders function.


99-117: LGTM on usage integration.

The _create_activity_with_substitution method correctly uses the centralized function with proper null-checking for activity.name before substitution. The refactor maintains the same behavior while removing code duplication.

src/tux/plugins/atl/fact.py (5)

22-22: LGTM on import update.

Correctly imports the centralized substitute_placeholders function, replacing the local helper.


85-96: LGTM on category lookup substitution.

Correctly applies placeholder substitution to category name matching and display name retrieval.


105-112: LGTM on fact content substitution.

Correctly applies placeholder substitution to both API-fetched facts and locally-stored facts.


134-143: LGTM on autocomplete substitution.

Correctly applies placeholder substitution to autocomplete choice names.


164-167: LGTM on error message substitution.

Correctly applies placeholder substitution when building the list of available category names for error messages.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Important

Action Needed: IP Allowlist Update

If your organization protects your Git platform with IP whitelisting, please add the new CodeRabbit IP address to your allowlist:

  • 136.113.208.247/32 (new)
  • 34.170.211.100/32
  • 35.222.179.152/32

Reviews will stop working after February 8, 2026 if the new IP is not added to your allowlist.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • Now that substitute_placeholders is shared, consider narrowing the contextlib.suppress(Exception) to the specific exceptions you actually expect (e.g. AttributeError, KeyError) so that genuine bugs in new call sites aren’t silently masked.
  • Since substitute_placeholders is now in a broadly used shared module, you might want to make the bot parameter type more flexible (e.g. a Protocol with just the attributes you use) instead of tying it specifically to Tux, which will make reuse easier and avoid import-cycle risks for future callers.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Now that `substitute_placeholders` is shared, consider narrowing the `contextlib.suppress(Exception)` to the specific exceptions you actually expect (e.g. `AttributeError`, `KeyError`) so that genuine bugs in new call sites aren’t silently masked.
- Since `substitute_placeholders` is now in a broadly used shared module, you might want to make the `bot` parameter type more flexible (e.g. a Protocol with just the attributes you use) instead of tying it specifically to `Tux`, which will make reuse easier and avoid import-cycle risks for future callers.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copy link

@amazon-q-developer amazon-q-developer bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The refactoring to centralize the substitute_placeholders function into shared/functions.py is implemented correctly. All imports have been updated appropriately, function calls have been migrated successfully, and the TYPE_CHECKING pattern is used properly to avoid circular imports. The changes maintain the existing functionality while improving code reusability.


You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request successfully centralizes the substitute_placeholders function into shared/functions.py, removing duplicated code from plugins/atl/fact.py and services/handlers/activity.py. This is a great refactoring for maintainability. My feedback includes a suggestion to improve the error handling in the new shared function to make it more robust and easier to debug.

Comment on lines +470 to +490
with contextlib.suppress(Exception):
# Build placeholder map only for placeholders present in text
placeholders: dict[str, str] = {}

if "{member_count}" in text:
placeholders["member_count"] = str(
sum(guild.member_count or 0 for guild in bot.guilds),
)
if "{guild_count}" in text:
placeholders["guild_count"] = str(len(bot.guilds) if bot.guilds else 0)
if "{bot_name}" in text:
placeholders["bot_name"] = CONFIG.BOT_INFO.BOT_NAME
if "{bot_version}" in text:
placeholders["bot_version"] = get_version()
if "{prefix}" in text:
placeholders["prefix"] = CONFIG.get_prefix()

# Single-pass substitution using format_map
if placeholders:
text = text.format_map(placeholders)
return text

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using contextlib.suppress(Exception) can hide important errors and make debugging difficult. It's better to catch exceptions and log them. This change will maintain the current behavior of returning the original text on failure but adds valuable logging for troubleshooting.

With this change, you can also remove the import contextlib and add from loguru import logger at the top of the file.

    try:
        # Build placeholder map only for placeholders present in text
        placeholders: dict[str, str] = {}

        if "{member_count}" in text:
            placeholders["member_count"] = str(
                sum(guild.member_count or 0 for guild in bot.guilds),
            )
        if "{guild_count}" in text:
            placeholders["guild_count"] = str(len(bot.guilds) if bot.guilds else 0)
        if "{bot_name}" in text:
            placeholders["bot_name"] = CONFIG.BOT_INFO.BOT_NAME
        if "{bot_version}" in text:
            placeholders["bot_version"] = get_version()
        if "{prefix}" in text:
            placeholders["prefix"] = CONFIG.get_prefix()

        # Single-pass substitution using format_map
        if placeholders:
            text = text.format_map(placeholders)
    except Exception as e:
        logger.warning(f"Failed to substitute placeholders in '{text}': {e}")
    return text

@sentry
Copy link

sentry bot commented Feb 3, 2026

❌ 2 Tests Failed:

Tests completed Failed Passed Skipped
664 2 662 36
View the full list of 2 ❄️ flaky test(s)
tests/cache/test_backend.py::TestValkeyBackend::test_setex_called_when_ttl_sec_provided

Flake rate in main: 100.00% (Passed 0 times, Failed 7 times)

Stack Traces | 0.005s run time
tests/cache/test_backend.py:162: in test_setex_called_when_ttl_sec_provided
    assert args[2] == "v"
E   assert '"v"' == 'v'
E     
E     #x1B[0m#x1B[91m- v#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
E     #x1B[92m+ "v"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
tests/cache/test_backend.py::TestValkeyBackend::test_string_value_stored_as_is

Flake rate in main: 100.00% (Passed 0 times, Failed 7 times)

Stack Traces | 0.008s run time
tests/cache/test_backend.py:128: in test_string_value_stored_as_is
    assert mock_client.set.call_args[0][1] == "plain"
E   assert '"plain"' == 'plain'
E     
E     #x1B[0m#x1B[91m- plain#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
E     #x1B[92m+ "plain"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
E     ? +     +#x1B[90m#x1B[39;49;00m

To view more test analytics, go to the [Prevent Tests Dashboard](https://All Things Linux.sentry.io/prevent/tests/?preventPeriod=30d&integratedOrgName=allthingslinux&repository=tux&branch=Ow0cast%2Ftux%3Amain)

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 4 files

Confidence score: 3/5

  • format_map() in src/tux/shared/functions.py can throw KeyError on unknown placeholders and the broad suppression means substitutions may silently fail, which could surface as missing or incorrect text at runtime.
  • contextlib.suppress(Exception) in src/tux/shared/functions.py violates the project’s error-handling guidelines and hides unexpected failures, increasing debugging risk.
  • Pay close attention to src/tux/shared/functions.py - silent exception suppression and placeholder handling could mask real errors.
Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="src/tux/shared/functions.py">

<violation number="1" location="src/tux/shared/functions.py:470">
P2: Rule violated: **Code Style and Architecture Guidelines**

Using `contextlib.suppress(Exception)` catches all exceptions silently without logging, violating the project's error handling guidelines. Per AGENTS.md, errors should be logged with context.

Consider either:
1. Catching specific expected exceptions (e.g., `KeyError` from `format_map`)
2. Adding logging before suppression to aid debugging
3. Using a more targeted approach that doesn't silently swallow programming errors</violation>

<violation number="2" location="src/tux/shared/functions.py:489">
P2: `format_map()` will raise `KeyError` on any unknown placeholder in `text` (e.g., `{user}`), causing the entire substitution to silently fail due to the broad exception suppression. Consider using a `dict` subclass with `__missing__` to preserve unknown placeholders instead of silently returning unchanged text.</violation>
</file>

Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Ask questions if you need clarification on any suggestion

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.


# Single-pass substitution using format_map
if placeholders:
text = text.format_map(placeholders)
Copy link

@cubic-dev-ai cubic-dev-ai bot Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: format_map() will raise KeyError on any unknown placeholder in text (e.g., {user}), causing the entire substitution to silently fail due to the broad exception suppression. Consider using a dict subclass with __missing__ to preserve unknown placeholders instead of silently returning unchanged text.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/tux/shared/functions.py, line 489:

<comment>`format_map()` will raise `KeyError` on any unknown placeholder in `text` (e.g., `{user}`), causing the entire substitution to silently fail due to the broad exception suppression. Consider using a `dict` subclass with `__missing__` to preserve unknown placeholders instead of silently returning unchanged text.</comment>

<file context>
@@ -432,3 +440,51 @@ def dec(obj: Any) -> Any:
+
+        # Single-pass substitution using format_map
+        if placeholders:
+            text = text.format_map(placeholders)
+    return text
</file context>
Fix with Cubic

if not text:
return text

with contextlib.suppress(Exception):
Copy link

@cubic-dev-ai cubic-dev-ai bot Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Rule violated: Code Style and Architecture Guidelines

Using contextlib.suppress(Exception) catches all exceptions silently without logging, violating the project's error handling guidelines. Per AGENTS.md, errors should be logged with context.

Consider either:

  1. Catching specific expected exceptions (e.g., KeyError from format_map)
  2. Adding logging before suppression to aid debugging
  3. Using a more targeted approach that doesn't silently swallow programming errors
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/tux/shared/functions.py, line 470:

<comment>Using `contextlib.suppress(Exception)` catches all exceptions silently without logging, violating the project's error handling guidelines. Per AGENTS.md, errors should be logged with context.

Consider either:
1. Catching specific expected exceptions (e.g., `KeyError` from `format_map`)
2. Adding logging before suppression to aid debugging
3. Using a more targeted approach that doesn't silently swallow programming errors</comment>

<file context>
@@ -432,3 +440,51 @@ def dec(obj: Any) -> Any:
+    if not text:
+        return text
+
+    with contextlib.suppress(Exception):
+        # Build placeholder map only for placeholders present in text
+        placeholders: dict[str, str] = {}
</file context>
Fix with Cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant