Skip to content

fix(sdk/python/core): honor kms_cache_file_name override in KSMCache cache path (KSM-1019) - #1046

Open
mgallego-keeper wants to merge 3 commits into
release/sdk/python/core/v17.4.0from
KSM-1019-honor-kms-cache-file-name-override
Open

fix(sdk/python/core): honor kms_cache_file_name override in KSMCache cache path (KSM-1019)#1046
mgallego-keeper wants to merge 3 commits into
release/sdk/python/core/v17.4.0from
KSM-1019-honor-kms-cache-file-name-override

Conversation

@mgallego-keeper

@mgallego-keeper mgallego-keeper commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Jira: KSM-1019 · Fixes #1044

Summary

PR #1034 (KSM-1004) rerouted KSMCache.save_cache / get_cached_data / remove_cache_file through a new get_cache_file_path() that re-derives the path from KSM_CACHE_DIR and no longer reads the kms_cache_file_name class attribute. As a result, assigning KSMCache.kms_cache_file_name = "/custom/path.bin" was silently ignored — a backward-incompatible change for consumers that set it (and it was the only way to customize the cache filename, since KSM_CACHE_DIR only controls the directory).

Changes

  • core.pyget_cache_file_path() returns an explicitly-overridden kms_cache_file_name (detected via an import-time default snapshot), otherwise resolves KSM_CACHE_DIR lazily at call time. KSM-1004: resolve KSMCache path lazily so KSM_CACHE_DIR is honored after import #1034's lazy behavior is preserved; the three cache methods already route through this method, so no caller changes were needed.
  • tests/cache_test.py — add test_kms_cache_file_name_override_is_honored.
  • Version bump 17.3.0 → 17.3.1 across the three coupled sources: _version.py, the keeper_globals.py hardcoded fallback (version_revision_default), and the smoke_test.py version assertions.

Behavior (verified)

Scenario Result
Explicit kms_cache_file_name override honored (regression fixed)
No override, no env var ksm_cache.bin in CWD (unchanged)
KSM_CACHE_DIR set after import, attribute untouched honored (KSM-1004 preserved)

Testing

cd sdk/python/core && python -m pytest tests/127 passed, 1 skipped locally.

Note: the Test-Python workflow only triggers on PRs targeting master, so it will not auto-run against this release branch — the suite was run locally instead.

Target

Point release on the v17.3.x line; base branch release/sdk/python/core/v17.3.1 (branched from the v17.3.0 release).

…cache path

PR #1034 (KSM-1004) routed cache operations through get_cache_file_path(), which
re-derived the path from KSM_CACHE_DIR and ignored the kms_cache_file_name class
attribute. Assigning KSMCache.kms_cache_file_name was silently dropped.

Honor an explicit kms_cache_file_name override again (detected via an import-time
default snapshot) while keeping lazy KSM_CACHE_DIR resolution. Add a regression test
and bump to 17.3.1 (including the keeper_globals hardcoded fallback and smoke-test
assertions).

Fixes #1044.

@stas-schaller stas-schaller left a comment

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.

Good work, two things before we go forward: README.md still ends at ### 17.3.0, needs a ### 17.3.1 entry.

Comment thread sdk/python/core/keeper_secrets_manager_core/core.py Outdated
Comment thread sdk/python/core/tests/cache_test.py
… (KSM-1019)

Replace the value-equality override check in KSMCache.get_cache_file_path with
an identity comparison against a _DefaultCachePath(str) sentinel, so an explicit
kms_cache_file_name assignment is honored even when its text equals the
import-time default (e.g. "ksm_cache.bin" when KSM_CACHE_DIR was unset at
import). The previous "!=" check silently dropped such an override once
KSM_CACHE_DIR was set, a narrower case of the KSM-1004 regression this line
fixes.

Add a collision-case regression test and the 17.3.1 README changelog entry.
KSM-1004 lazy KSM_CACHE_DIR resolution and all default behavior are preserved.
@mgallego-keeper

Copy link
Copy Markdown
Contributor Author

Thanks for the review — all three points addressed in 6e590b0:

  • core.py — override detection now uses object identity against a _DefaultCachePath(str) sentinel instead of value-equality, so an override whose text equals the default is no longer silently dropped.
  • cache_test.py — added the collision-case regression test (fails on the old != code, passes after the fix).
  • README.md — added the ### 17.3.1 changelog entry above ### 17.3.0.

Full suite green locally: python -m pytest tests/ → 128 passed, 1 skipped. Re-requesting review.

…d into 17.4.0)

This fix is being consolidated into the 17.4.0 release. The single version
bump and the KSM-1019 changelog entry now live in the 17.4.0 release PR
(#1057), so revert _version.py, keeper_globals.py, smoke_test.py and the
README changelog back to the release-branch baseline. This PR now carries
only the KSMCache code fix and its regression tests.
@mgallego-keeper
mgallego-keeper changed the base branch from release/sdk/python/core/v17.3.1 to release/sdk/python/core/v17.4.0 July 9, 2026 22:46
@stas-schaller
stas-schaller force-pushed the release/sdk/python/core/v17.4.0 branch from d541f29 to c80bdd5 Compare July 24, 2026 17:38

@stas-schaller stas-schaller left a comment

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.

Good progress on the identity-sentinel approach, and both of my previous comments are addressed. Three more things before this can merge.

1. Rewrite the PR description. The body still describes a 17.3.1 point release with a version bump across _version.py, keeper_globals.py, and smoke_test.py. None of that is in this PR — the diff is two files and the version reads 17.3.0 at head. The PR was retargeted to release/sdk/python/core/v17.4.0 and the last commit deliberately dropped the version bump, which is the right call, but the description was never updated to match. Please rewrite it to reflect what the PR actually does: fix lands in 17.4.0, no version bump included here. Also correct the test count from 127 to 128 (the second test was added after the description was written).

2. Extract the duplicated default-path expression (inline comment below).

3. Fix the misleading restore-default note and add a restore test (inline comment below).

if cls.kms_cache_file_name is not cls._default_cache_file_name:
return cls.kms_cache_file_name
# Otherwise resolve the directory from KSM_CACHE_DIR at call time.
return os.path.join(os.environ.get("KSM_CACHE_DIR", ""), 'ksm_cache.bin')

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.

This expression is identical to the one on line 1924 that builds _default_cache_file_name. The identity check works because the sentinel and the lazy branch are two separate objects, but the correctness of that check depends on both expressions producing the same text. Change the filename in one place and they silently disagree, with no test catching the drift.

Extract a module-level helper so there is one source of truth:

def _default_cache_path():
    return os.path.join(os.environ.get("KSM_CACHE_DIR", ""), 'ksm_cache.bin')

class _DefaultCachePath(str):
    pass

class KSMCache:
    _default_cache_file_name = _DefaultCachePath(_default_cache_path())
    kms_cache_file_name = _default_cache_file_name

    @classmethod
    def get_cache_file_path(cls):
        if cls.kms_cache_file_name is not cls._default_cache_file_name:
            return cls.kms_cache_file_name
        return _default_cache_path()

# if unset, the cache file is created in the current working directory. Assigning
# kms_cache_file_name directly overrides the full path (backward compatibility); the
# override is detected by object identity against this sentinel, so it holds even when
# the assigned value equals the default text. (Re-assign _default_cache_file_name to

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.

The note (Re-assign _default_cache_file_name to restore the default.) reads as an instruction to modify _default_cache_file_name itself, which would corrupt the sentinel for every future caller. The intent is the opposite: reassign kms_cache_file_name back to the sentinel.

Change to: (To restore the default, assign KSMCache.kms_cache_file_name = KSMCache._default_cache_file_name.)

Also worth adding a test that exercises this restore path, since the comment describes it and nothing currently locks in the correct way to do it:

def test_kms_cache_file_name_override_can_be_restored_to_default(self):
    original = KSMCache.kms_cache_file_name
    KSMCache.kms_cache_file_name = "/some/custom/path.bin"
    KSMCache.kms_cache_file_name = KSMCache._default_cache_file_name
    try:
        # After restore, lazy env resolution must work again.
        with unittest.mock.patch.dict(os.environ, {"KSM_CACHE_DIR": "/lazy/dir"}):
            self.assertEqual(
                KSMCache.get_cache_file_path(),
                "/lazy/dir/ksm_cache.bin",
                "restoring kms_cache_file_name to _default_cache_file_name should re-enable lazy KSM_CACHE_DIR resolution",
            )
    finally:
        KSMCache.kms_cache_file_name = original

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