Skip to content

Delete shared default options after context - #59

Open
pbrubeck wants to merge 14 commits into
mainfrom
pbrubeck/delete-default-options
Open

pbrubeck wants to merge 14 commits into
mainfrom
pbrubeck/delete-default-options

Conversation

@pbrubeck

@pbrubeck pbrubeck commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #58.

On main, an OptionsManager with a default_options_set writes shared defaults under its own prefix. inserted_options() leaves those entries in PETSc's global options database, so a later manager with the same prefix can mistake them for options the user supplied.

This change includes shared-default keys in to_delete before scanning options under the manager's prefix. At context exit, those keys are removed; existing prefixed options outside the shared defaults remain. A child-prefixed value for a shared default takes precedence while options are inserted.

Tests cover cleanup for sequential managers with multiple prefixes and the case where a child-prefixed value overrides a shared default.

This PR was written with Claude Code.

🤖 Generated with Claude Code

OptionsManager built to_delete before it merged the default options into
parameters. inserted_options() therefore inserted the inherited options
under the prefix of the manager and never deleted them. Build to_delete
from the merged parameters instead. The loop that follows still keeps
every option that the database already held.

Fixes #58.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread tests/test_options.py Outdated
@pbrubeck
pbrubeck requested a review from connorjward October 5, 2026 14:43

@JHopeCollins JHopeCollins left a comment

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.

Thanks for spotting this. The default options are useful but not widely used so I'm not surprised this slipped through!

Please can we use a different word than "inherited" for the default options though? "inherited" has too much implied meaning in a language with object inheritance that doesn't apply here.

Comment thread tests/test_options.py
Comment on lines +190 to +192
options["parent_ksp_type"] = "cg"
options["parent_0_pc_type"] = "jacobi"
opts_before = dict(options.getAll())

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.

Please can you test:

  1. having multiple prefixes in the set (i.e. at least parent_0 and parent_1), and calling inserted_options on both in turn (not nested).
  2. The case where a default option gets overridden? e.g. -parent_ksp_type cg -parent_1_ksp_type gmres

Comment thread petsctools/options.py Outdated
Comment on lines +520 to +523
# Keep existing options, except inherited defaults, which
# are temporary copies under this prefix.
if key not in inherited_options:
to_delete.discard(key)

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.

This comment is not clear, please can you rewrite it? I would suggest two sentences, one explaining what happens for non-default and one for default.

Comment thread petsctools/options.py Outdated
# Start building parameters from the defaults so
# that they will overwritten by any other source.
parameters = default_options | parameters
inherited_options = set(default_options)

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.

If default_options isn't used as a dictionary again then I think its fine just to rebind it to the set.

Suggested change
inherited_options = set(default_options)
default_options = set(default_options)

Comment thread petsctools/options.py Outdated
to_delete.discard(key)
# Keep existing options, except inherited defaults, which
# are temporary copies under this prefix.
if key not in inherited_options:

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.

Suggested change
if key not in inherited_options:
if key not in default_options:

@pbrubeck pbrubeck changed the title Delete the options inherited through default_options_set Delete shared default options after context Oct 5, 2026
Comment thread petsctools/options.py Outdated
# Start building parameters from the defaults so
# that they will overwritten by any other source.
parameters = default_options | parameters
default_options = set(default_options)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't think this line is needed

Comment thread petsctools/options.py Outdated
Comment on lines +520 to +524
# Existing keys outside the shared defaults are kept after
# this context. Shared-default keys stay in to_delete and are
# removed on exit.
if key not in default_options:
to_delete.discard(key)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This doesn't seem right to me. We should simply be removing anything that isn't already in the database

Comment thread tests/test_options.py Outdated
Comment on lines +206 to +209
@pytest.mark.skipnopetsc4py
def test_inserted_options_deletes_defaults_for_multiple_prefixes():
"""Check shared defaults are removed for sequential child managers."""
from petsc4py import PETSc

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.

What is the reasoning for having these as three separate tests? It'd be simpler just to have one test that covers all these cases.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The advantage to keeping separate tests is that one can easily tell when individual features break. But we also want to be covering the interaction between these features, so it makes sense to merge them into a single test, so I did this.

Comment thread petsctools/options.py Outdated
pbrubeck and others added 2 commits October 7, 2026 09:43
Co-authored-by: Josh Hope-Collins <joshua.hope-collins13@imperial.ac.uk>
Co-authored-by: Josh Hope-Collins <joshua.hope-collins13@imperial.ac.uk>
Comment thread petsctools/options.py
Comment thread petsctools/options.py Outdated
Comment thread petsctools/options.py Outdated
Comment thread petsctools/options.py

This branch has not been deployed

No deployments
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.

OptionsManager does not delete options inherited through default_options_set

3 participants