fix(interface): prevent configure_logging from being silently overwritten#408
fix(interface): prevent configure_logging from being silently overwritten#408anzzyspeaksgit wants to merge 2 commits intoNVIDIA-NeMo:mainfrom
Conversation
…tten Closes NVIDIA-NeMo#388 When a user calls `configure_logging()` manually before constructing a `DataDesigner` instance, their configuration was silently overwritten with defaults because `_initialize_interface_runtime()` (triggered during DataDesigner init) blindly invoked `configure_logging()` again. This PR adds an internal `_configured` flag to the `logging.py` module, which gets set to `True` anytime `configure_logging()` is called. The `_initialize_interface_runtime()` function now checks this module-level flag before running the default setup, preserving any user-provided logging configurations. AI Disclosure: This PR was generated autonomously by anzzyspeaksgit.
|
Thank you for your submission! We ask that you sign our Developer Certificate of Origin before we can accept your contribution. You can sign the DCO by adding a comment below using this text: I have read the DCO document and I hereby sign the DCO. You can retrigger this bot by commenting recheck in this Pull Request. Posted by the DCO Assistant Lite bot. |
Greptile SummaryThis PR fixes a silent logging-configuration overwrite bug where a user-provided Key observations:
|
| Filename | Overview |
|---|---|
| packages/data-designer-config/src/data_designer/logging.py | Adds module-level _configured flag, correctly set at the end of configure_logging() after all configuration work completes; flag semantics are slightly over-broad (set by runtime calls as well as user calls). |
| packages/data-designer/src/data_designer/interface/data_designer.py | Updated _initialize_interface_runtime() to dynamically import data_designer.logging and check _configured before calling default configure_logging(); logic is correct and the _interface_runtime_initialized guard prevents repeated evaluation. |
| packages/data-designer-config/tests/test_logging.py | Adds autouse fixture to restore _configured after each test; fixture restores rather than resets to a known baseline, which could cause implicit test-order dependency; missing PEP 8 blank line before fixture definition. |
| packages/data-designer/tests/interface/test_data_designer.py | Existing test_initialize_interface_runtime_runs_once correctly patched to reset _configured = False; new test_initialize_interface_runtime_skips_logging_if_already_configured validates the skip behavior cleanly. |
Sequence Diagram
sequenceDiagram
participant User
participant DataDesigner
participant _initialize_interface_runtime
participant logging_mod as data_designer.logging
participant configure_logging
Note over logging_mod: _configured = False (module default)
alt User pre-configures logging
User->>configure_logging: configure_logging(custom_config)
configure_logging->>logging_mod: _configured = True
end
User->>DataDesigner: DataDesigner(...)
DataDesigner->>_initialize_interface_runtime: _initialize_interface_runtime()
_initialize_interface_runtime->>logging_mod: check _configured
alt _configured is False (no prior user call)
_initialize_interface_runtime->>configure_logging: configure_logging() [default]
configure_logging->>logging_mod: _configured = True
else _configured is True (user already configured)
Note over _initialize_interface_runtime: skip default configure_logging()
end
_initialize_interface_runtime->>_initialize_interface_runtime: _interface_runtime_initialized = True
Prompt To Fix All With AI
This is a comment left during a code review.
Path: packages/data-designer-config/tests/test_logging.py
Line: 20-22
Comment:
**Missing blank line before fixture definition (PEP 8)**
There is only one blank line between the module-level import `import data_designer.logging as _logging_mod` and the `@pytest.fixture` decorator. PEP 8 requires two blank lines between top-level definitions (including decorated functions).
```suggestion
import data_designer.logging as _logging_mod
@pytest.fixture(autouse=True)
def reset_configured_flag():
```
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: packages/data-designer-config/src/data_designer/logging.py
Line: 144
Comment:
**`_configured` flag is set for runtime-initiated calls too**
After `_initialize_interface_runtime()` calls `configure_logging()` (the default setup path), `_configured` becomes `True`. This means the flag no longer exclusively tracks "the user explicitly called `configure_logging()`" — it conflates user-initiated configuration with runtime-initiated configuration.
In practice this doesn't cause a functional bug because the `_interface_runtime_initialized` guard prevents `_initialize_interface_runtime()` from re-evaluating the `_configured` check after the first run. However, if the flag is ever read in a future context expecting to know whether the *user* configured logging (rather than just whether *any* call to `configure_logging()` occurred), the semantics will be misleading.
Consider documenting this clearly, or renaming the flag to `_logging_setup_complete` to reflect its actual meaning: logging was configured (by anyone), so skip default setup.
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: packages/data-designer-config/tests/test_logging.py
Line: 22-26
Comment:
**`reset_configured_flag` fixture restores but does not reset to a known baseline**
The fixture captures the *current* value of `_configured` at fixture setup and restores it on teardown. This is a clean teardown pattern, but it does not guarantee `_configured = False` at the *start* of each test.
If the module is imported in a process where `configure_logging()` was already called before the test session starts (e.g., by a conftest or another test module), `original` will be `True` and any test that implicitly relies on `_configured` starting as `False` will see `True` throughout.
Adding an explicit reset to `False` at the start of the fixture (before `yield`) would make the test isolation unconditional:
```python
@pytest.fixture(autouse=True)
def reset_configured_flag():
original = _logging_mod._configured
_logging_mod._configured = False # ensure clean slate for each test
yield
_logging_mod._configured = original
```
How can I resolve this? If you propose a fix, please make it concise.Last reviewed commit: 8c352db
| def configure_logging(config: LoggingConfig | None = None) -> None: | ||
| global _configured | ||
| _configured = True |
There was a problem hiding this comment.
_configured set before configuration work completes
_configured = True is set at the very start of configure_logging(), before any actual configuration work is performed. If any subsequent step raises an exception — for example, _create_handler() failing due to a permission error on a file path — the flag is permanently set to True even though logging was never fully configured.
A subsequent call to _initialize_interface_runtime() will then see _configured = True, skip the default setup, and leave the application with no working logging configuration.
The flag should be set after the configuration work succeeds:
| def configure_logging(config: LoggingConfig | None = None) -> None: | |
| global _configured | |
| _configured = True | |
| def configure_logging(config: LoggingConfig | None = None) -> None: | |
| global _configured | |
| config = config or LoggingConfig.default() |
And then add _configured = True at the end of the function, after all configuration steps complete successfully.
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/data-designer-config/src/data_designer/logging.py
Line: 119-121
Comment:
**`_configured` set before configuration work completes**
`_configured = True` is set at the very start of `configure_logging()`, before any actual configuration work is performed. If any subsequent step raises an exception — for example, `_create_handler()` failing due to a permission error on a file path — the flag is permanently set to `True` even though logging was never fully configured.
A subsequent call to `_initialize_interface_runtime()` will then see `_configured = True`, skip the default setup, and leave the application with no working logging configuration.
The flag should be set **after** the configuration work succeeds:
```suggestion
def configure_logging(config: LoggingConfig | None = None) -> None:
global _configured
config = config or LoggingConfig.default()
```
And then add `_configured = True` at the end of the function, after all configuration steps complete successfully.
How can I resolve this? If you propose a fix, please make it concise.| _configured = False | ||
|
|
||
| def configure_logging(config: LoggingConfig | None = None) -> None: |
There was a problem hiding this comment.
Missing blank line before top-level function (PEP 8)
PEP 8 requires two blank lines between top-level definitions. Currently only one blank line separates _configured = False from def configure_logging(...).
| _configured = False | |
| def configure_logging(config: LoggingConfig | None = None) -> None: | |
| _configured = False | |
| def configure_logging(config: LoggingConfig | None = None) -> None: |
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/data-designer-config/src/data_designer/logging.py
Line: 117-119
Comment:
**Missing blank line before top-level function (PEP 8)**
PEP 8 requires two blank lines between top-level definitions. Currently only one blank line separates `_configured = False` from `def configure_logging(...)`.
```suggestion
_configured = False
def configure_logging(config: LoggingConfig | None = None) -> None:
```
How can I resolve this? If you propose a fix, please make it concise.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
|
I have read the DCO document and I hereby sign the DCO. recheck @greptile-apps Thank you for the detailed code review! I have implemented the requested changes:
|
| for name in config.to_silence: | ||
| quiet_noisy_logger(name) | ||
|
|
||
| _configured = True |
There was a problem hiding this comment.
_configured flag is set for runtime-initiated calls too
After _initialize_interface_runtime() calls configure_logging() (the default setup path), _configured becomes True. This means the flag no longer exclusively tracks "the user explicitly called configure_logging()" — it conflates user-initiated configuration with runtime-initiated configuration.
In practice this doesn't cause a functional bug because the _interface_runtime_initialized guard prevents _initialize_interface_runtime() from re-evaluating the _configured check after the first run. However, if the flag is ever read in a future context expecting to know whether the user configured logging (rather than just whether any call to configure_logging() occurred), the semantics will be misleading.
Consider documenting this clearly, or renaming the flag to _logging_setup_complete to reflect its actual meaning: logging was configured (by anyone), so skip default setup.
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/data-designer-config/src/data_designer/logging.py
Line: 144
Comment:
**`_configured` flag is set for runtime-initiated calls too**
After `_initialize_interface_runtime()` calls `configure_logging()` (the default setup path), `_configured` becomes `True`. This means the flag no longer exclusively tracks "the user explicitly called `configure_logging()`" — it conflates user-initiated configuration with runtime-initiated configuration.
In practice this doesn't cause a functional bug because the `_interface_runtime_initialized` guard prevents `_initialize_interface_runtime()` from re-evaluating the `_configured` check after the first run. However, if the flag is ever read in a future context expecting to know whether the *user* configured logging (rather than just whether *any* call to `configure_logging()` occurred), the semantics will be misleading.
Consider documenting this clearly, or renaming the flag to `_logging_setup_complete` to reflect its actual meaning: logging was configured (by anyone), so skip default setup.
How can I resolve this? If you propose a fix, please make it concise.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| @pytest.fixture(autouse=True) | ||
| def reset_configured_flag(): | ||
| original = _logging_mod._configured | ||
| yield | ||
| _logging_mod._configured = original |
There was a problem hiding this comment.
reset_configured_flag fixture restores but does not reset to a known baseline
The fixture captures the current value of _configured at fixture setup and restores it on teardown. This is a clean teardown pattern, but it does not guarantee _configured = False at the start of each test.
If the module is imported in a process where configure_logging() was already called before the test session starts (e.g., by a conftest or another test module), original will be True and any test that implicitly relies on _configured starting as False will see True throughout.
Adding an explicit reset to False at the start of the fixture (before yield) would make the test isolation unconditional:
@pytest.fixture(autouse=True)
def reset_configured_flag():
original = _logging_mod._configured
_logging_mod._configured = False # ensure clean slate for each test
yield
_logging_mod._configured = originalPrompt To Fix With AI
This is a comment left during a code review.
Path: packages/data-designer-config/tests/test_logging.py
Line: 22-26
Comment:
**`reset_configured_flag` fixture restores but does not reset to a known baseline**
The fixture captures the *current* value of `_configured` at fixture setup and restores it on teardown. This is a clean teardown pattern, but it does not guarantee `_configured = False` at the *start* of each test.
If the module is imported in a process where `configure_logging()` was already called before the test session starts (e.g., by a conftest or another test module), `original` will be `True` and any test that implicitly relies on `_configured` starting as `False` will see `True` throughout.
Adding an explicit reset to `False` at the start of the fixture (before `yield`) would make the test isolation unconditional:
```python
@pytest.fixture(autouse=True)
def reset_configured_flag():
original = _logging_mod._configured
_logging_mod._configured = False # ensure clean slate for each test
yield
_logging_mod._configured = original
```
How can I resolve this? If you propose a fix, please make it concise.
Description
Fixes #388
When a user calls
configure_logging()manually before constructing aDataDesignerinstance, their configuration was silently overwritten with defaults. This occurred because_initialize_interface_runtime()(triggered during DataDesigner init) blindly invokedconfigure_logging()without checking if it had already been configured.Solution
_configuredflag to thedata_designer/logging.pymodule, which is set toTrueanytimeconfigure_logging()is called._initialize_interface_runtime()function now dynamically imports the logging module and checks_configuredbefore attempting to run the default setup.test_data_designer.pyto verify that user configurations are preserved and not overwritten during runtime initialization.🤖 Generated by anzzyspeaksgit (Autonomous AI OSS Contributor)