Skip to content

Conversation

Vikranth3140
Copy link

@Vikranth3140 Vikranth3140 commented Sep 3, 2025

Description

This PR implements support for making material and problem-level default libraries “None-able,” addressing Issue #801.

Summary of changes

  • Updated __setitem__ for default_libraries mapping:

    • Assigning None to a default library key (e.g., "nlib", "plib", or LibraryType.NEUTRON) now unsets/deletes the entry.
    • Non-None assignments remain backward-compatible (Library or str).
  • Updated update() so that passing {"nlib": None} or keyword nlib=None also unsets correctly.

  • Serializer logic verified to omit unset defaults (no "None" literal is emitted).

  • Adjusted type checks and docstrings to clarify accepted values (Library | str | None).

Behavior

  • Before:

    • Reading a missing default returned None.
    • But assigning None raised an error or resulted in an invalid literal "None" in output.
  • After:

    • Reading a missing default still returns None.
    • Assigning None now unsets the default, and it is omitted from serialization.

Fixes #801


General Checklist


Documentation Checklist

  • I have documented all added classes and methods.
  • For infrastructure updates, I have updated the developer's guide.
  • For significant new features, I have added a section to the getting started guide.

First-Time Contributor Checklist

  • If this is your first contribution, add yourself to pyproject.toml if you wish to do so.

Additional Notes for Reviewers

Ensure that:

@MicahGale
Copy link
Collaborator

Thanks @Vikranth3140 for this contribution. I'm a bit busy right now and it will be a little while before I can review this.

Did you use the help of an LLM (e.g., ChatGPT, claude, Copilot, etc.) to prepare this PR? We are still working on our exact policy, but using LLMs is fine as long as this use is disclosed.

@MicahGale
Copy link
Collaborator

This is not part of my review, I just noticed that on coveralls I noticed the patch coverage is 80%. We really aim for 100% patch coverage unless a good reason this isn't possible is provided. I thought while you wait on my review you could work on the test coverage.

@Vikranth3140
Copy link
Author

Thanks @Vikranth3140 for this contribution. I'm a bit busy right now and it will be a little while before I can review this.

Did you use the help of an LLM (e.g., ChatGPT, claude, Copilot, etc.) to prepare this PR? We are still working on our exact policy, but using LLMs is fine as long as this use is disclosed.

Hi, Yes, I had written the base code and optimized it using Copilot and also written the tests/test_material.py using it.

@Vikranth3140
Copy link
Author

This is not part of my review, I just noticed that on coveralls I noticed the patch coverage is 80%. We really aim for 100% patch coverage unless a good reason this isn't possible is provided. I thought while you wait on my review you could work on the test coverage.

Hi, so the add_rtd_link is failing because my workflow permissions are read-only and does not accept accept modifications from a PR

@MicahGale
Copy link
Collaborator

This is not part of my review, I just noticed that on coveralls I noticed the patch coverage is 80%. We really aim for 100% patch coverage unless a good reason this isn't possible is provided. I thought while you wait on my review you could work on the test coverage.

Hi, so the add_rtd_link is failing because my workflow permissions are read-only and does not accept accept modifications from a PR

Here is the documentation build: https://montepy--802.org.readthedocs.build/en/802/

Yes I know about this issue and I don't know of a good workaround yet. It's completely fine to ignore that failure though.

@Vikranth3140
Copy link
Author

This is not part of my review, I just noticed that on coveralls I noticed the patch coverage is 80%. We really aim for 100% patch coverage unless a good reason this isn't possible is provided. I thought while you wait on my review you could work on the test coverage.

Hi, so the add_rtd_link is failing because my workflow permissions are read-only and does not accept accept modifications from a PR

Here is the documentation build: https://montepy--802.org.readthedocs.build/en/802/

Yes I know about this issue and I don't know of a good workaround yet. It's completely fine to ignore that failure though.

Okay cool

@Vikranth3140
Copy link
Author

Hi @MicahGale, is there any update on this PR

Copy link
Collaborator

@MicahGale MicahGale left a comment

Choose a reason for hiding this comment

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

This still needs some improvements.

  1. This does not fix #801, but rather #800.
  2. Some editorial changes for clarity
  3. The new update method is not necessary for #800. It could be helpful, but currently is not being effectively tested. So I would say either remove it or make the testing more thorough to get 100% coverage.

Coverage report because coveralls is currently down. The current CI failure is due to Coveralls being done, so you don't need to worry about it.
htmlcov.zip


**Features Added**

* Allow clearing default libraries by assigning ``None`` at material and problem scopes; unset values are omitted from serialization.
Copy link
Collaborator

Choose a reason for hiding this comment

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

I do not follow the "unset values are omitted from serialization" aspect, and I'm not sure it's true. Also I don't think such a technical detail is needed in a changelog.

This needs to be linked to an issue well. See the below bug fix.

Comment on lines +62 to +71
def update(self, other=None, **kwargs):
"""Update the default libraries with the key/value pairs from other, overwriting existing keys.
Parameters
----------
other : dict or dict-like
Another dict or dict-like object to update from
**kwargs
Additional key-value pairs to update
"""
Copy link
Collaborator

Choose a reason for hiding this comment

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

This doc string is rather generic, and is not very specific to this class. It might benefit from an example. I could imagine it being used in the following way (which is not a full example):

mat.default_libraries.update({"nlib": "80c", "plib": "80p"})

That being said this is not required for fixing #800, and could be dropped from this PR if needed.

Comment on lines +72 to +73
if other is not None:
if hasattr(other, "items"):
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is a user-facing function, so the inputs cannot be trusted. A lot of the type and value enforcement will be handled by __setitem__, however you will need to ensure that other is a dictionary prior to iterating over it.

:func:`~montepy.data_inputs.material.Material.default_libraries` acts like a dictionary,
and can accept a string or a :class:`~montepy.particle.LibraryType` as keys.
To clear a default library, assign ``None``:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
To clear a default library, assign ``None``:
A default library can be cleared by assigning it to be ``None``:

:func:`~montepy.data_inputs.material.Material.default_libraries` acts like a dictionary,
and can accept a string or a :class:`~montepy.particle.LibraryType` as keys.
To clear a default library, assign ``None``:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
To clear a default library, assign ``None``:
A default library can be cleared by assigning it to be ``None``:

Comment on lines 210 to +211
To set the default libraries for a problem you need to set this dictionary
to a Library or string.
to a Library or string. To clear a default library, assign ``None``.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
To set the default libraries for a problem you need to set this dictionary
to a Library or string.
to a Library or string. To clear a default library, assign ``None``.
To set the default libraries for a problem you need to set the values of this dictionary
to a Library or string.
to a Library or string. To clear a default library, set the value to ``None``.

Comment on lines +881 to +885
def test_default_libraries_none_setting(_, dl):
"""Test that setting default libraries to None unsets them."""
# Set a library first
dl["plib"] = "80p"
assert dl["plib"] == Library("80p")
Copy link
Collaborator

Choose a reason for hiding this comment

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

As discussed the patch coverage is currently 80% so more testing is needed. I suspect most of the needed testing is for more atypical ways to call these changes.

# Test update method with None
dl["nlib"] = "00c"
dl["plib"] = "80p"
dl.update({"plib": None})
Copy link
Collaborator

Choose a reason for hiding this comment

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

This only tests one way that this can be called. You need to also test:

  1. calling it with just kwargs
  2. Calling it with other and kwargs
  3. calling with not a dictionary
  4. other=None
  5. etc.

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.

Fill in blank exception messages
2 participants