-
Notifications
You must be signed in to change notification settings - Fork 598
Description
Description
-- The openmc.Settings class currently allows arbitrary dynamic attribute assignment, e.g.:
settings = openmc.Settings()
settings.sources = definedsource # typo: should be "settings.source"
settings.particle = 1000 # typo: should be "settings.particles"
settings.xxxxx = source # completely unknown attributeImpact
1. Silent failures
A simple typo, such as: settings.particle = 1000, does not raise an exception. The user believes the setting is applied, but OpenMC actually uses the default particles value.
2. Simulations complete successfully
Because OpenMC ignores unknown attributes, the simulation runs normally, producing output files without any indication of misconfiguration.
3. Results may be severely wrong
Incorrect settings (e.g., wrong particle count, wrong run mode, wrong cutoff parameters) can lead to:
-- incorrect eigenvalue estimates
-- incorrect tally statistics
-- incorrect variance reduction behavior
-- incorrect source distribution
These errors propagate silently.
4. Debugging is extremely difficult
Users may spend hours or days trying to understand why results are inconsistent, without realizing the root cause is a simple typo that OpenMC silently ignored.
Alternatives
- Expected Behavior
OpenMC should reject unknown attributes assigned to Settings objects, raising an explicit error so users can immediately detect configuration mistakes. - Proposed Solution
Introduce a restrictive setattr implementation in Settings that:
Allows internal _xxx attributes during initialization
Allows assignment to existing attributes (including properties)
Allows internal _xxx attributes after initialization
Rejects all unknown attributes with a clear error message
- Suggested Implementation in openmc.settings
def __setattr__(self, name, value):
# 1. During initialization: allow all _xxx attributes
if getattr(self, '_initializing', False):
super().__setattr__(name, value)
return
# 2. Allow existing attributes (including properties)
if hasattr(self, name):
super().__setattr__(name, value)
return
# 3. Allow internal attributes (_xxx)
if name.startswith('_'):
super().__setattr__(name, value)
return
# 4. Otherwise → forbid
raise AttributeError(f"Unknown Settings attribute '{name}'")