Skip to content

fix(slurm): handle integer slurm_account values from YAML parsing#448

Open
andchamorro wants to merge 1 commit intosnakemake:mainfrom
andchamorro:fix/integer-account-handling
Open

fix(slurm): handle integer slurm_account values from YAML parsing#448
andchamorro wants to merge 1 commit intosnakemake:mainfrom
andchamorro:fix/integer-account-handling

Conversation

@andchamorro
Copy link
Copy Markdown

@andchamorro andchamorro commented Apr 2, 2026

Summary

Snakemake's YAML parser automatically converts numeric-looking strings (e.g., "123456789") to integers when populating job.resources. This caused account.lower() in test_account() to fail since int has no lower() method.

Changes

Convert slurm_account and account values to strings before use in re.split() and shlex.quote() calls to handle both string and integer values.

Tests

Added 4 new unit tests covering:

  • String account values
  • Integer account values (from YAML parsing)
  • Multiple string accounts
  • Multiple integer accounts

Summary by CodeRabbit

  • Bug Fixes

    • Normalize SLURM account inputs (including numeric values) to strings, ensure accounts are properly split and quoted so submission arguments are consistently formatted.
  • Tests

    • Added unit tests validating single, numeric, and multi-account scenarios to ensure correct account argument generation and formatting.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 2, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ae222c64-3d83-4f07-a0fc-9de788d4d633

📥 Commits

Reviewing files that changed from the base of the PR and between ae009be and 67cd465.

📒 Files selected for processing (2)
  • snakemake_executor_plugin_slurm/__init__.py
  • tests/test_account.py
✅ Files skipped from review due to trivial changes (1)
  • snakemake_executor_plugin_slurm/init.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/test_account.py

Walkthrough

Coerces job.resources.slurm_account to str before regex-splitting in get_account_arg, ensuring numeric YAML-parsed accounts are tokenized and quoted as strings. Adds unit tests validating single-string, integer, and multi-account parsing and emitted -A arguments.

Changes

Cohort / File(s) Summary
Account coercion logic
snakemake_executor_plugin_slurm/__init__.py
Coerce job.resources.slurm_account via str(...) before re.split(...); ensure emitted sbatch -A arguments use the string form (and are quoted consistently).
Account argument tests
tests/test_account.py
Add tests for Executor.get_account_arg() covering: single-string account, integer account normalized to string, and multi-account strings split by commas/spaces; assert produced -A <account> args and test_account() calls.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 I nibbled bytes and made them neat,
Numbers turned to strings, a tidy feat.
Accounts split clean, each one in line,
Tests hop in place — everything's fine. 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main fix: converting integer slurm_account values from YAML parsing to strings to prevent AttributeError.
Docstring Coverage ✅ Passed Docstring coverage is 92.31% 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 unit tests (beta)
  • Create PR with unit tests

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
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
tests/test_array_jobs.py (1)

685-692: Test name is misleading: tests single integer, not multiple accounts.

The test name test_multiple_accounts_integer suggests it tests multiple integer accounts, but it only tests a single integer value 123. Consider renaming to test_single_integer_account for clarity, or update the docstring to reflect the actual test purpose.

♻️ Proposed fix for naming clarity
     `@patch`("snakemake_executor_plugin_slurm.get_account")
     `@patch`("snakemake_executor_plugin_slurm.test_account")
-    def test_multiple_accounts_integer(self, mock_test_account, mock_get_account, tmp_path):
-        """Multiple integer accounts work correctly."""
+    def test_single_integer_account(self, mock_test_account, mock_get_account, tmp_path):
+        """Single integer account is converted to string correctly."""
         executor = self._make_executor_stub()
         job = _make_mock_job(slurm_account=123)
         results = list(executor.get_account_arg(job))
         assert results == [" -A 123"]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_array_jobs.py` around lines 685 - 692, The test function name and
docstring are misleading—rename the test function test_multiple_accounts_integer
to test_single_integer_account and update its docstring from "Multiple integer
accounts work correctly." to "Single integer account works correctly." to match
the actual behavior; locate the test by the function name
test_multiple_accounts_integer and references to
_make_mock_job(slurm_account=123) and executor.get_account_arg to make the
change.
snakemake_executor_plugin_slurm/__init__.py (1)

1595-1605: Consider removing duplicate test_account calls.

Each account is validated twice: once in the first loop (lines 1595-1598) and again in the second loop (line 1604). The first validation pass is sufficient.

♻️ Proposed fix to remove duplicate validation
         accounts = [
             a for a in re.split(r"[,\s]+", str(job.resources.slurm_account)) if a
         ]
         for account in accounts:
             # here, we check whether the given or guessed account is valid
             # if not, a WorkflowError is raised
             test_account(account, self.logger)
         # sbatch only allows one account per submission
         # yield one after the other, if multiple were given
         # we have to quote the account, because it might
         # contain build-in shell commands - see issue `#354`
         for account in accounts:
-            test_account(account, self.logger)
             yield f" -A {shlex.quote(str(account))}"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@snakemake_executor_plugin_slurm/__init__.py` around lines 1595 - 1605, The
code calls test_account twice for each entry in accounts — once in the initial
for loop and again inside the yield loop; remove the first validation loop so
each account is validated only once, keeping the validation call in the yield
loop (test_account(account, self.logger)) before yielding f" -A
{shlex.quote(str(account))}" to preserve the behavior and logging; ensure no
other code relies on the removed loop.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@snakemake_executor_plugin_slurm/__init__.py`:
- Around line 1595-1605: The code calls test_account twice for each entry in
accounts — once in the initial for loop and again inside the yield loop; remove
the first validation loop so each account is validated only once, keeping the
validation call in the yield loop (test_account(account, self.logger)) before
yielding f" -A {shlex.quote(str(account))}" to preserve the behavior and
logging; ensure no other code relies on the removed loop.

In `@tests/test_array_jobs.py`:
- Around line 685-692: The test function name and docstring are
misleading—rename the test function test_multiple_accounts_integer to
test_single_integer_account and update its docstring from "Multiple integer
accounts work correctly." to "Single integer account works correctly." to match
the actual behavior; locate the test by the function name
test_multiple_accounts_integer and references to
_make_mock_job(slurm_account=123) and executor.get_account_arg to make the
change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 69d92cfd-ca73-4e22-96ec-16e0dc53400b

📥 Commits

Reviewing files that changed from the base of the PR and between 7fa975f and b9346af.

📒 Files selected for processing (2)
  • snakemake_executor_plugin_slurm/__init__.py
  • tests/test_array_jobs.py

Copy link
Copy Markdown
Member

@cmeesters cmeesters left a comment

Choose a reason for hiding this comment

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

Thank you for your contribution! I left a couple of comments to address. Generally speaking, I am happy to accept.

for account in accounts:
test_account(account, self.logger)
yield f" -A {shlex.quote(account)}"
yield f" -A {shlex.quote(str(account))}"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

is this conversion necessary, if you convert an account to str before?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

It isn't specifically necessary for the situation I encountered; it's a preventive measure suggested by Sonnet.

self.logger.warning(f"Guessed SLURM account: {account}")
test_account(f"{account}", self.logger)
self._fallback_account_arg = f" -A {shlex.quote(account)}"
self._fallback_account_arg = f" -A {shlex.quote(str(account))}"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

is this conversion necessary, after the conversion which happened already?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

It isn't specifically necessary for the situation I encountered; it's a preventive measure suggested by Sonnet.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I understand the reason, but would rather have a comment about the type (I will introduce more and more type annotations to functions) and where it has been set than redundant conversions.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I agree, I will remove the edits and leave some comments.

executor.report_job_error.assert_not_called()


class TestGetAccountArg:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

account testing ought not to go into the array test script

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

My mistake, I just associate array with slurm arrays. I will move to test/test_account.py

executor._fallback_account_arg = None
return executor

@patch("snakemake_executor_plugin_slurm.get_account")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why these patches?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

unittest mock patch decorator that replace get_account() and test_account(). Replace the real function with MagicMock objects.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

ah yes. Mind leaving a comment? Or I would stumble across this and accidentally remove it sometime into the future.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I will leave a comment in the new test location tests/test_account.py.

@andchamorro andchamorro force-pushed the fix/integer-account-handling branch from b9346af to 7b06a22 Compare April 7, 2026 16:36
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/test_account.py (1)

47-83: Consider asserting fallback path is not used in explicit-account tests.

Since these tests provide slurm_account, adding mock_get_account.assert_not_called() would make regressions in control flow easier to catch.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_account.py` around lines 47 - 83, For each test that supplies an
explicit slurm_account (test_string_account, test_integer_account,
test_multiple_accounts_string, test_multiple_accounts_integer), assert that the
fallback get_account path was not used by adding
mock_get_account.assert_not_called() after the existing assertions; locate the
checks in the respective test_* functions that call
executor.get_account_arg(job) and insert the
mock_get_account.assert_not_called() immediately after the result assertions to
ensure regressions in control flow are caught.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/test_account.py`:
- Around line 78-83: Replace the single numeric account in
test_multiple_accounts_integer with a comma-delimited numeric string (e.g.,
slurm_account="123,456") so the test actually covers splitting numeric-looking
multi-accounts; then update the assertion to verify get_account_arg(job)
produces entries for both account IDs (check for both "123" and "456" in the
produced argument(s) or match the same multi-account output format used by other
tests), referencing test_multiple_accounts_integer, _make_mock_job, and
get_account_arg to locate the change.

---

Nitpick comments:
In `@tests/test_account.py`:
- Around line 47-83: For each test that supplies an explicit slurm_account
(test_string_account, test_integer_account, test_multiple_accounts_string,
test_multiple_accounts_integer), assert that the fallback get_account path was
not used by adding mock_get_account.assert_not_called() after the existing
assertions; locate the checks in the respective test_* functions that call
executor.get_account_arg(job) and insert the
mock_get_account.assert_not_called() immediately after the result assertions to
ensure regressions in control flow are caught.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 78910a52-6b68-4be9-8650-8f4ce4aa8972

📥 Commits

Reviewing files that changed from the base of the PR and between b9346af and 7b06a22.

📒 Files selected for processing (2)
  • snakemake_executor_plugin_slurm/__init__.py
  • tests/test_account.py
✅ Files skipped from review due to trivial changes (1)
  • snakemake_executor_plugin_slurm/init.py

Comment on lines +78 to +83
def test_multiple_accounts_integer(self, mock_test_account, mock_get_account, tmp_path):
"""Multiple integer accounts work correctly."""
executor = self._make_executor_stub()
job = _make_mock_job(slurm_account=123)
results = list(executor.get_account_arg(job))
assert results == [" -A 123"] No newline at end of file
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

test_multiple_accounts_integer does not actually test multiple accounts.

On Line 81, slurm_account=123 yields only one account, so this case doesn’t validate multi-account splitting for numeric-looking values as the test name/docstring suggests.

Proposed test correction
-    def test_multiple_accounts_integer(self, mock_test_account, mock_get_account, tmp_path):
-        """Multiple integer accounts work correctly."""
+    def test_multiple_numeric_accounts(self, mock_test_account, mock_get_account, tmp_path):
+        """Multiple numeric account tokens are split and emitted correctly."""
         executor = self._make_executor_stub()
-        job = _make_mock_job(slurm_account=123)
+        job = _make_mock_job(slurm_account="123,456 789")
         results = list(executor.get_account_arg(job))
-        assert results == [" -A 123"]
+        assert results == [" -A 123", " -A 456", " -A 789"]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_account.py` around lines 78 - 83, Replace the single numeric
account in test_multiple_accounts_integer with a comma-delimited numeric string
(e.g., slurm_account="123,456") so the test actually covers splitting
numeric-looking multi-accounts; then update the assertion to verify
get_account_arg(job) produces entries for both account IDs (check for both "123"
and "456" in the produced argument(s) or match the same multi-account output
format used by other tests), referencing test_multiple_accounts_integer,
_make_mock_job, and get_account_arg to locate the change.

@andchamorro andchamorro force-pushed the fix/integer-account-handling branch from 7b06a22 to ae009be Compare April 7, 2026 16:47
Snakemake's YAML parser automatically converts numeric-looking strings
(e.g. "123456789") to integers when populating job.resources. This
caused account.lower() in test_account() to fail since int has no
lower() method.

Convert slurm_account and account values to strings before use in
re.split() and shlex.quote() calls.

Fixes the issue where users specifying slurm_account as a numeric
string in their YAML profile would get an AttributeError.
@andchamorro andchamorro force-pushed the fix/integer-account-handling branch from ae009be to 67cd465 Compare April 8, 2026 15:35
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.

2 participants