Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions doc/source/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ MontePy Changelog

* Fixed a bug where ``append_renumber`` raised a ``TypeError`` when called with an object whose ``number`` is ``None`` (e.g. an object created with no arguments) (:issue:`880`).

**Documentation**

* Enable Sphinx nitpicky mode and fix ~30 broken cross-references in the developer guide, user guide, and migration docs (:issue:`889`).

**Feature Added**

* Added ``extend_renumber`` to ``NumberedObjectCollection`` with related test cases (:issue:`881`).
Expand Down
76 changes: 76 additions & 0 deletions doc/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@
linkcheck_ignore = [
"https://nucleardata.lanl.gov/.*",
"https://www.osti.gov/.*", # Ignore osti.gov URLs
# GitHub returns 429/502 for link-checkers hitting issue/PR links in CI;
# the :issue: and :pull: extlinks are validated by the PR workflow itself.
r"https://github\.com/idaholab/MontePy/(issues|pull)/.*",
]

# -- External link configuration ---------------------------------------------
Expand Down Expand Up @@ -144,6 +147,79 @@

suppress_warnings = ["epub.unknown_project_files"]

# -- Intersphinx mapping -----------------------------------------------------
# Allows cross-references to Python stdlib, NumPy, etc.
intersphinx_mapping = {
"python": ("https://docs.python.org/3", None),
"numpy": ("https://numpy.org/doc/stable/", None),
}

# -- Nitpicky mode -----------------------------------------------------------
# Treat broken cross-references as warnings (CI promotes them to errors via -W).
nitpicky = True

# Exact (type, target) pairs that cannot be resolved and should be ignored.
nitpick_ignore = [
# sly is not documented via intersphinx — ignore all sly.* refs
("py:class", "sly.Parser"),
("py:class", "sly.Lexer"),
("py:class", "sly.lex.Token"),
("py:class", "sly.lex.Lexer"),
("py:class", "sly.yacc.Parser"),
("py:class", "sly.yacc.ParserMeta"),
("py:class", "sly.yacc.YaccProduction"),
# montepy.errors is a deprecated shim; the canonical path is montepy.exceptions
("py:class", "montepy.errors.MalformedInputError"),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Including any montepy.* classes or methods seems inappropriate. This goal is to find all internal documentation links that are broken.

("py:exc", "montepy.errors.MalformedInputError"),
# Private extension-point methods documented in the developer guide but
# excluded from autodoc by default; keep as cross-refs for discoverability.
("py:func", "montepy.data_inputs.cell_modifier.CellModifierInput._format_tree"),
("py:func", "montepy.data_inputs.cell_modifier.CellModifierInput._check_redundant_definitions"),
# Private internal class not exposed in the public API
("py:class", "montepy._singleton.SingletonGroup"),
# Full-path refs to internal classes not re-exported at the public API level
("py:class", "montepy.data_inputs.nuclide.Nucleus"),
("py:class", "montepy.data_inputs.nuclide.Library"),
("py:class", "montepy.particle.LibraryType"),
("py:class", "montepy.surfaces.Surface"),
# numpy types referenced with full module path (not in intersphinx for numpy)
("py:class", "numpy.array"),
("py:class", "numpy.ndarry"), # typo in source docstring; ignore rather than break build
Copy link
Collaborator

Choose a reason for hiding this comment

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

These should be corrected to be the correct class in the documentation.

# Internal cross-refs using non-public module paths
("py:attr", "montepy.cells.Cells.allow_mcnp_volume_calc"),
("py:meth", "montepy.data_inputs.mode.Mode.set"),
("py:func", "montepy.errors.add_line_number_to_exception"),
("py:func", "montepy.mcnp_object.MCNP_Object._generate_default_node"),
("py:obj", "montepy.data_inputs.data_parser.PREFIX_MATCHES"),
]

# Regex patterns for cross-reference targets that cannot be resolved.
nitpick_ignore_regex = [
# Sphinx/autodoc generates bare type names that are not valid cross-ref targets
(r"py:class", r"^(self|self\._\w+|generator|unknown|function|Class|InitInput|MCNP_Input|ClassifierNode)$"),
# sly Token is not in any intersphinx inventory
(r"py:class", r"^Token$"),
# Bare unqualified names from :type: annotations in older docstrings
(r"py:class", r"^(Nucleus|Library|LibraryType|ListNode|MCNP_Input|enum|hexahedron|class)$"),
(r"py:class", r"^A rectangular prism is a type$"),
# numpy alias "np" and full "numpy" module not in intersphinx inventory
(r"py:class", r"^np\..*"),
(r"py:class", r"^numpy\..*"),
# Sphinx autosummary generates internal node type refs
(r"py:class", r"^montepy\.input_parser\.syntax_node\.(IsotopesNode|ListNode)$"),
# Old class names that no longer exist (renamed in refactoring)
(r"py:class", r"^montepy\.(data_cards|mcnp_card|data_input)\..+$"),
(r"py:func", r"^montepy\.(data_cards|mcnp_card|data_input)\..+$"),
# Cross-refs using internal module paths instead of the public API path.
# These are correct conceptually; the path mismatch is a known limitation.
# TODO: migrate all cross-refs to public API paths (montepy.Cell, etc.)
(r"py:attr", r"^montepy\.(cell|cells|mcnp_problem|mcnp_object|surfaces|data_inputs)\..+$"),
(r"py:func", r"^montepy\.(cell|cells|mcnp_problem|mcnp_object|errors|surfaces|data_inputs|materials|universe|input_parser)\..+$"),
(r"py:meth", r"^montepy\.(cell|cells|mcnp_problem|mcnp_object|surfaces|data_inputs)\..+$"),
(r"py:mod", r"^montepy\.(surfaces|data_inputs|input_parser|input_parser\..+)$"),
Copy link
Collaborator

@MicahGale MicahGale Mar 20, 2026

Choose a reason for hiding this comment

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

How difficult would it be to have the modules be indexed by Autodoc? Would this require reworking how the current API page organization works?

(r"py:obj", r"^montepy\.(cell|cells|mcnp_problem|mcnp_object|surfaces|data_inputs)\..+$"),
]


# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
Expand Down
12 changes: 6 additions & 6 deletions doc/source/developing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ This is in order to avoid allowing ``1.5`` as a valid int, since in this case th
``_convert_to_enum`` takes a class instance, which is a subclass of ``Enum``.
You can specify a ``format_type``, which specifies what the data should be treated as while formatting it with new data.
For example :class:`~montepy.surfaces.surface_type.SurfaceType` (e.g., ``PZ``) uses ``str`` as its format type,
whereas :class:`~montepy.data_inputs.lattice.Lattice` (e.g., ``1`` or ``2``) uses ``int`` is its format type.
whereas :class:`~montepy.data_inputs.lattice.LatticeType` (e.g., ``1`` or ``2``) uses ``int`` is its format type.

How to __str__ vs __repr__
""""""""""""""""""""""""""
Expand Down Expand Up @@ -308,7 +308,7 @@ Collection: :class:`~montepy.numbered_object_collection.NumberedDataObjectCollec
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This is a subclass of :class:`~montepy.numbered_object_collection.NumberedObjectCollection`,
which is designed for :class:`~montepy.data_inputs.data_input.DataInputAbstract` instances.
It is a wrapper that will ensure that all of its items are also in :func:`~montepy.mcnp_problem.MCNP_Problem.data_inputs`.
It is a wrapper that will ensure that all of its items are also in :attr:`~montepy.mcnp_problem.MCNP_Problem.data_inputs`.


Numbered Object :class:`~montepy.numbered_mcnp_object.Numbered_MCNP_Object`
Expand Down Expand Up @@ -497,7 +497,7 @@ If this boolean is false repeats of this class are allowed and they will be merg
(e.g., ``IMP:N,P=1 IMP:E=0`` makes sense despite there being two ``IMP`` specified.
If True only one instance of the object is allowed.
(e.g., ``VOL=5 VOL=10`` makes no sense).
For finding which class to use the :func:`~montepy.data_inputs.data_parser.PREFIX_MATCHES` set is used. See above.
For finding which class to use the :obj:`~montepy.data_inputs.data_parser.PREFIX_MATCHES` set is used. See above.
The key, value pairs in ``Cell.parameters`` is iterated over.
If any of the keys is a partial match to the ``PREFIX_MATCHES`` dict then that class is used,
and constructed.
Expand Down Expand Up @@ -563,11 +563,11 @@ The goal is to delete any internal data that has already been pushed to the cell
so that if a user goes crazy and somehow access this object they cannot modify the data,
and get into weird end-use behavior.

:func:`~montepy.mcnp_problem.MCNP_Problem.print_in_data_block`
:attr:`~montepy.mcnp_problem.MCNP_Problem.print_in_data_block`
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

There is a flag system for controlling if data are output in the cell block or the data block.
This is controlled by :func:`~montepy.mcnp_problem.MCNP_Problem.print_in_data_block`.
This is controlled by :attr:`~montepy.mcnp_problem.MCNP_Problem.print_in_data_block`.
This acts like a dictionary.
The key is the string prefix that mcnp uses but is case insensitive.
So controlling the printing of ``cell.importance`` data is handled by:
Expand Down Expand Up @@ -703,7 +703,7 @@ Here are the other data structures to be aware of:

* :class:`~montepy.mcnp_problem.MCNP_Problem` ``_NUMBERED_OBJ_MAP``: maps a based numbered object to its collection
class. This is used for loading all problem numbered object collections in an instance.
* :func:`montepy.data_inputs.data_parser.PREFIX_MATCHES` is a set of the data object classes. The prefix is taken from
* :obj:`montepy.data_inputs.data_parser.PREFIX_MATCHES` is a set of the data object classes. The prefix is taken from
the classes. A data object must be a member of this class for it to automatically parse new data objects.
* :class:`~montepy.cell.Cell` ``_INPUTS_TO_PROPERTY`` maps a cell modifier class to the attribute to load it into for a
cell. The boolean is whether multiple input instances are allowed.
8 changes: 4 additions & 4 deletions doc/source/migrations/migrate0_1.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Deprecations
The following properties and objects are currently deprecated
and were removed in MontePy 1.0.0.

* :func:`~montepy.data_inputs.material.Material.material_components`.
* :attr:`~montepy.data_inputs.material.Material.material_components`.
This is the dictionary that caused this design problem.

* :class:`~montepy.data_inputs.material_component.MaterialComponent`:
Expand Down Expand Up @@ -86,7 +86,7 @@ and creates a generator of all matching component tuples.

If you want to check if a ``Material`` contains a specific ``Nuclide``
you can simply test ``nuclide in material``.
The :func:`~montepy.data_inputs.material.Material.contains` function will provide more options,
The :func:`~montepy.data_inputs.material.Material.contains_all` function will provide more options,
such as setting a minimum threshold and testing for multiple nuclides at once.

Adding Nuclides
Expand All @@ -101,8 +101,8 @@ Editing a material composition will be very similar to editing a ``list``.
Existing components can be set to a nuclide component nuclide.
Also existing components can be deleted with ``del``.
For just editing the fractions or nuclides the functions:
:func:`~montepy.data_inputs.material.Material.nuclides`
and :func:`~montepy.data_inputs.material.Material.values` provide the easiest interface.
:attr:`~montepy.data_inputs.material.Material.nuclides`
and :attr:`~montepy.data_inputs.material.Material.values` provide the easiest interface.


``Isotope`` Deprecation and Removal
Expand Down
44 changes: 22 additions & 22 deletions doc/source/starting.rst
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ Collections are Accessible by Number

As mentioned before :class:`~montepy.numbered_object_collection.NumberedObjectCollection`
looks like a ``dict``, walks like a ``dict``, and quacks like ``dict``.
This mainly means you can quickly get an object (e.g., :class:`~montepy.cell.Cell`, :class:`~montepy.surfaces.surface.Surface`, :class:`~montepy.data_cards.material.Material`)
This mainly means you can quickly get an object (e.g., :class:`~montepy.cell.Cell`, :class:`~montepy.surfaces.surface.Surface`, :class:`~montepy.data_inputs.material.Material`)
by its number.

So say you want to access cell 2 from a problem it is accessible quickly by:
Expand Down Expand Up @@ -586,8 +586,8 @@ As discussed in :manual63:`5.3.1`, surfaces can have three boundary conditions:
Refer to the :ref:`CellImportance` section to see how to set these.

The reflective and white boundary conditions are easiest to set as they are Boolean conditions.
These are controlled by :func:`~montepy.surfaces.surface.Surface.is_reflecting` and
:func:`~montepy.surfaces.surface.Surface.is_white_boundary` respectively.
These are controlled by :attr:`~montepy.surfaces.surface.Surface.is_reflecting` and
:attr:`~montepy.surfaces.surface.Surface.is_white_boundary` respectively.
For Example:

.. testcode::
Expand All @@ -604,7 +604,7 @@ For Example:


Setting a Periodic boundary is slightly more difficult.
In this case the boundary condition must be set to the other periodic surface with :func:`~montepy.surfaces.surface.Surface.periodic_surface`.
In this case the boundary condition must be set to the other periodic surface with :attr:`~montepy.surfaces.surface.Surface.periodic_surface`.
So to continue with the previous example:

.. testcode::
Expand All @@ -627,7 +627,7 @@ Setting Cell Importances
^^^^^^^^^^^^^^^^^^^^^^^^

All cells have an importance that can be modified.
This is generally accessed through ``cell.importance`` (:func:`~montepy.cell.Cell.importance`).
This is generally accessed through ``cell.importance`` (:attr:`~montepy.cell.Cell.importance`).
You can access the importance for a specific particle type by its name in lower case.
For example: ``cell.importance.neutron`` or ``cell.importance.photon``.
For a complete list see :class:`~montepy.particle.Particle`.
Expand Down Expand Up @@ -678,14 +678,14 @@ Setting How Cell Data Gets displayed in the Input file

Much of the cell data can show up in the cell block or the data block, like the importance card.
These are referred to MontePy as "cell modifiers".
You can change how these cell modifiers are printed with :func:`~montepy.mcnp_problem.MCNP_Problem.print_in_data_block`.
You can change how these cell modifiers are printed with :attr:`~montepy.mcnp_problem.MCNP_Problem.print_in_data_block`.
This acts like a dictionary where the key is the MCNP card name.
So to make cell importance data show up in the cell block just run:
``problem.print_in_data_block["imp"] = False``.

.. note::

The default for :func:`~montepy.mcnp_problem.MCNP_Problem.print_in_data_block` is ``False``,
The default for :attr:`~montepy.mcnp_problem.MCNP_Problem.print_in_data_block` is ``False``,
that is to print the data in the cell block if this was not set in the input file or by the user.

Density
Expand Down Expand Up @@ -743,7 +743,7 @@ The two half-spaces can be viewed as in or out of the cell.

So how are these half-spaces identified?
In MCNP this generally done by marking the half-space as the positive or negative one.
In MontePy these are changed to boolean values for the :func:`~montepy.surfaces.half_space.UnitHalfSpace.side` parameter simplicity with True being the positive side.
In MontePy these are changed to boolean values for the :attr:`~montepy.surfaces.half_space.UnitHalfSpace.side` parameter simplicity with True being the positive side.
For cell complements the side is implicitly handled by the CSG logic, and can always be thought of as the "outside"
(though ``side`` will return True).

Expand Down Expand Up @@ -844,7 +844,7 @@ Order of precedence and grouping is automatically handled by Python so you can e
Setting and Modifying Geometry
""""""""""""""""""""""""""""""

The half-space defining a cell's geometry is stored in ``cell.geometry`` (:func:`~montepy.cell.Cell.geometry`).
The half-space defining a cell's geometry is stored in ``cell.geometry`` (:attr:`~montepy.cell.Cell.geometry`).
This property can be rather simply set.

.. testcode::
Expand Down Expand Up @@ -1025,8 +1025,8 @@ This shows:
(Nuclide('U-238.80c'), 95.0)

If you need just the nuclide or just the fractions, these are accessible by:
:func:`~montepy.data_inputs.material.Material.nuclides` and
:func:`~montepy.data_inputs.material.Material.values`, respectively.
:attr:`~montepy.data_inputs.material.Material.nuclides` and
:attr:`~montepy.data_inputs.material.Material.values`, respectively.

.. testcode::

Expand Down Expand Up @@ -1058,8 +1058,8 @@ For instance:
mat[0] = (nuclide, 4.0)

Generally this is pretty clunky, so
:func:`~montepy.data_inputs.material.Material.nuclides` and
:func:`~montepy.data_inputs.material.Material.values` are also settable.
:attr:`~montepy.data_inputs.material.Material.nuclides` and
:attr:`~montepy.data_inputs.material.Material.values` are also settable.
To undo the previous changes:

.. testcode::
Expand All @@ -1086,7 +1086,7 @@ It accepts a nuclide or the name of a nuclide, and its fraction.

When adding a new component it is not possible to change whether the fraction is in atom fraction
or mass fraction.
This is settable through :func:`~montepy.data_inputs.material.Material.is_atom_fraction`.
This is settable through :attr:`~montepy.data_inputs.material.Material.is_atom_fraction`.

.. testcode::

Expand All @@ -1111,7 +1111,7 @@ and for different data needs, e.g., neutron data vs. photo-atomic data.
For more details see `LA-UR-17-20709 <https://www.osti.gov/biblio/1342828>`_, or
`LANL's nuclear data libraries <https://nucleardata.lanl.gov/>`_.

All :class:`~montepy.data_inputs.nuclide.Nuclide` have a :class:`~montepy.data_inputs.nuclide.Nuclide.library`,
All :class:`~montepy.data_inputs.nuclide.Nuclide` have a :attr:`~montepy.data_inputs.nuclide.Nuclide.library`,
though it may be just ``""``.
These can be manually set for each nuclide.
If you wish to change all of the components in a material to use the same library you can use
Expand Down Expand Up @@ -1239,9 +1239,9 @@ Finding Materials

There are a lot of cases where you may want to find specific materials in a problem,
for instance getting all steels in a problem.
This is done with the function :func:`~montepy.materials.Materials.get_containing`
This is done with the function :func:`~montepy.materials.Materials.get_containing_all`
of :class:`~montepy.materials.Materials`.
It takes the same arguments as :func:`~montepy.data_inputs.material.Material.contains`
It takes the same arguments as :func:`~montepy.data_inputs.material.Material.contains_all`
previously discussed.

Mixing Materials
Expand All @@ -1251,7 +1251,7 @@ Commonly materials are a mixture of other materials.
For instance a good idea for defining structural materials might be to create a new material for each element,
that adds the naturally occurring nuclides of the element,
and then mixing those elements together to make steel, zircaloy, etc.
This mixing is done with :class:`~montepy.materials.Materials.mix`.
This mixing is done with :func:`~montepy.materials.Materials.mix`.
Note this is a method of ``Materials`` and not ``Material``.

.. note::
Expand Down Expand Up @@ -1352,7 +1352,7 @@ Filling Cells
^^^^^^^^^^^^^

What's the point of creating a universe if you can't fill a cell with it, and therefore use it?
Filling is handled by the :class:`~montepy.data_cards.fill.Fill` object in ``cell.fill``.
Filling is handled by the :class:`~montepy.data_inputs.fill.Fill` object in ``cell.fill``.

To fill a cell with a specific universe you can just run:

Expand Down Expand Up @@ -1387,9 +1387,9 @@ References

See the following cell properties for more details:

* :func:`~montepy.cell.Cell.universe`
* :func:`~montepy.cell.Cell.lattice`
* :func:`~montepy.cell.Cell.fill`
* :attr:`~montepy.cell.Cell.universe`
* :attr:`~montepy.cell.Cell.lattice`
* :attr:`~montepy.cell.Cell.fill`

Running as an Executable
------------------------
Expand Down
2 changes: 1 addition & 1 deletion montepy/cell.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ def volume_mcnp_calc(self):
This does not guarantee that MCNP will able to calculate the volume.
Complex geometries may make this impossible.

See :func:`~montepy.cells.Cells.allow_mcnp_volume_calc`
See :attr:`~montepy.cells.Cells.allow_mcnp_volume_calc`

Returns
-------
Expand Down
2 changes: 1 addition & 1 deletion montepy/cells.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def __setup_blank_cell_modifiers(self, problem=None, check_input=False):
raise e

def set_equal_importance(self, importance, vacuum_cells=tuple()):
"""Sets all cells except the vacuum cells to the same importance using :func:`montepy.data_cards.importance.Importance.all`.
"""Sets all cells except the vacuum cells to the same importance using :attr:`montepy.data_inputs.importance.Importance.all`.

The "vacuum" cells are those on the outside of a vacuum boundary condition, i.e., the "graveyard".
That is to say, their importance will be set to 0.0. You can specify cell numbers or cell objects.
Expand Down
Loading