Repository navigation
fix: improve virlrc key parsing accuracy and ensure cross-platform test reliability - #275
hardikkaurani wants to merge 4 commits into
Conversation
…lrc parser Signed-off-by: Hardik Kaurani <hardikkaurani1@gmail.com>
… parsing Signed-off-by: Hardik Kaurani <hardikkaurani1@gmail.com>
Signed-off-by: Hardik Kaurani <hardikkaurani1@gmail.com>
Signed-off-by: Hardik Kaurani <hardikkaurani1@gmail.com>
|
Hi @tmikuska, I've opened this PR to address key matching accuracy in
All 4 commits include DCO sign-offs, and flake8 checks are completely clean. Whenever you have a chance, please let me know if you'd like any adjustments. Thank you! |
| try: | ||
| with virlrc.open(encoding="utf-8") as fh: | ||
| config = fh.readlines() | ||
| except (OSError, UnicodeDecodeError): |
There was a problem hiding this comment.
[Minor (New) - Confidence: 90%]
Catching OSError / UnicodeDecodeError and returning None makes a present-but-unreadable cwd .virlrc indistinguishable from a missing file. _get_prop then falls through to ~/.virlrc, so a non-UTF-8 or unreadable local file silently uses home credentials.
Reproduced: a binary cwd .virlrc caused _get_prop("VIRL2_USER") to return the home-file user.
If the file exists (is_file() already passed), prefer failing loud or logging a warning rather than treating a read error as “key not found”.
There was a problem hiding this comment.
Resolved! When an existing .virlrc file cannot be read due to an OSError or UnicodeDecodeError, the error is now logged as a warning with the file path and re-raised instead of returning None. This prevents silently falling back to home credentials when a local .virlrc file exists but is unreadable. Added the regression test test_get_from_file_decode_and_os_error_fails_loud to cover this behavior.
| with virlrc.open() as fh: | ||
| config = fh.readlines() | ||
| try: | ||
| with virlrc.open(encoding="utf-8") as fh: |
There was a problem hiding this comment.
[Minor (New) - Confidence: 90%]
Windows Notepad “UTF-8” files typically start with a BOM. encoding="utf-8" decodes that as U+FEFF on the first key (\ufeffVIRL2_USER), so the lookup returns None. That undercuts the Windows reliability goal of this change.
utf-8-sig strips a leading BOM and is a no-op for BOM-less files.
| with virlrc.open(encoding="utf-8") as fh: | |
| with virlrc.open(encoding="utf-8-sig") as fh: |
There was a problem hiding this comment.
Adopted! Updated open() to use encoding="utf-8-sig" across virl2_client.py and test fixtures, cleanly stripping leading BOM characters. Added unit test test_get_from_file_utf8_bom to verify UTF-8 BOM files are parsed accurately.
| @@ -134,7 +144,12 @@ def _get_prop(cls, prop_name: str) -> str | None: | |||
| if prop := cls._get_from_file(Path.cwd(), prop_name): | |||
There was a problem hiding this comment.
[Minor (Pre-existing) - Confidence: 85%]
if prop := cls._get_from_file(...) treats an empty string as missing, so VIRL2_USER="", VIRL2_USER='', or VIRL2_USER= in the cwd file falls through to ~/.virlrc. Reproduced: cwd empty quoted user → home user.
The walrus check is pre-existing; unquoting single quotes newly turns '' into "" and hits the same path. Consider if prop is not None.
There was a problem hiding this comment.
Good catch! Changed to prop = cls._get_from_file(Path.cwd(), prop_name) followed by if prop is not None: return prop (and removed or None on the home directory fallback). Empty values like VIRL2_USER="", VIRL2_USER='', or VIRL2_USER= in the cwd .virlrc now return "" immediately without falling through to home credentials, as verified by test_get_prop_empty_value_does_not_fall_through_to_home.
| _ = ClientLibrary(ssl_verify=False) | ||
|
|
||
|
|
||
| def test_get_from_file_exact_key_and_quotes(tmp_path: Path): |
There was a problem hiding this comment.
[Minor (New) - Confidence: 85%]
Good coverage for the prefix clash (VIRL2_USER vs VIRL2_USERNAME), comments, surrounding whitespace, and quote stripping. The parser rewrite still has no tests for:
- UTF-8 BOM on the first key
UnicodeDecodeError/OSErroron a present file- empty values (
"",'',VIRL2_USER=) VIRL2_PASScontaining=(split("=", 1)is still correct; worth locking in)
There was a problem hiding this comment.
Added dedicated unit tests in tests/test_configuration.py covering all 4 cases:
test_get_from_file_utf8_bom: verifies BOM on the first key (\xef\xbb\xbfVIRL2_USER) is stripped and matches.test_get_from_file_decode_and_os_error_fails_loud: verifiesUnicodeDecodeErrorandOSErrorraise and fail loud when reading an existing file.test_get_from_file_empty_values_and_value_with_equals: verifies"",'', and bare empty values (EMPTY_BARE=), as well as passwords containing=characters (p@ss=word=123).test_get_prop_empty_value_does_not_fall_through_to_home: verifies cwd empty values return""without falling back to home credentials.
| yield path | ||
|
|
||
| os.remove(path) | ||
| if path.is_file(): |
There was a problem hiding this comment.
[Nit (New) - Confidence: 95%]
tmp_path already deletes the directory after the test, and monkeypatch restores cwd / Path.home. The os.remove teardown is unnecessary (same for home_virlrc below).
There was a problem hiding this comment.
Removed! Cleaned up the redundant os.remove teardown in both cwd_virlrc and home_virlrc fixtures and removed the unused import os.
AI-Assisted Code Review SummaryThis is an AI-assisted review of the Verdict: request changes on the decode/BOM fallthrough (findings 1–2). Exact-key matching and the No linked Jira ticket (external contribution). Minor
Nit
Things done well
Inline comments are on the relevant lines. I have not requested reviewers or changed the PR description. |
|
Hi @tmikuska, Thank you for the thorough review and helpful reproduction cases! I have addressed all the feedback and pushed the updates in commit
Validation
Please take a look whenever you have a moment. Thank you! |
Summary
When resolving configuration properties from
.virlrc:ClientConfig._get_from_fileusedline.startswith(prop_name), which caused false-positive prefix matches (e.g. queryingVIRL2_USERincorrectly matchedVIRL2_USERNAME="admin"). Additionally, leading whitespace before keys and comments was not stripped, and single-quoted values ('val') were not unquoted.virlrc.open()used system-default encoding instead of explicitutf-8, causing potentialUnicodeDecodeErroron non-UTF-8 default platforms.Path.home()cannot resolve the user directory,_get_propraised an unhandledRuntimeError.tests/test_configuration.py, thehome_virlrcfixture relied on modifyingos.environ["HOME"], which failed on Windows whereHOMEis not set by default (TypeError: str expected, not NoneTypein teardown) andPath.home()does not useHOME.Changes
ClientConfig._get_from_file: ignores blank lines and comments (#), strips whitespace around keys and=, enforces exact key equality (key.strip() == prop_name), and unquotes both single and double quotes..virlrcexplicitly withencoding="utf-8"and handles file reading errors gracefully.RuntimeErroronPath.home()inClientConfig._get_propto safely returnNonewhen home cannot be determined.cwd_virlrcandhome_virlrcfixtures intests/test_configuration.pyto usemonkeypatch(monkeypatch.chdirandmonkeypatch.setattr(Path, "home", ...)), enabling 100% reliable execution across Linux, macOS, and Windows.test_get_from_file_exact_key_and_quotes: verifies exact key matching and quote unquoting.test_get_prop_home_runtime_error: verifies graceful fallback when home directory resolution raisesRuntimeError.Validation