diff --git a/doc/source/api/montepy.particle.rst b/doc/source/api/montepy.particle.rst index 7b887d96..42d3cb64 100644 --- a/doc/source/api/montepy.particle.rst +++ b/doc/source/api/montepy.particle.rst @@ -4,6 +4,5 @@ montepy.particle module .. automodule:: montepy.particle :members: - :inherited-members: :undoc-members: :show-inheritance: diff --git a/doc/source/api/montepy.surfaces.surface_type.rst b/doc/source/api/montepy.surfaces.surface_type.rst index ec5e4d77..cbec5e51 100644 --- a/doc/source/api/montepy.surfaces.surface_type.rst +++ b/doc/source/api/montepy.surfaces.surface_type.rst @@ -4,6 +4,5 @@ montepy.surfaces.surface\_type module .. automodule:: montepy.surfaces.surface_type :members: - :inherited-members: :undoc-members: :show-inheritance: diff --git a/doc/source/changelog.rst b/doc/source/changelog.rst index 8d810620..67e2f4b2 100644 --- a/doc/source/changelog.rst +++ b/doc/source/changelog.rst @@ -11,7 +11,7 @@ MontePy Changelog **Features Added** * Redesigned how Materials hold Material_Components. See :ref:`migrate 0 1` (:pull:`507`). -* Made it easier to create an Isotope, or now Nuclide: ``montepy.Nuclide("H-1.80c")`` (:issue:`505`). +* Made it easier to create an Isotope (now Nuclide): ``montepy.Nuclide("H-1.80c")`` (:issue:`505`). * When a typo in an object attribute is made an Error is raised rather than silently having no effect (:issue:`508`). * Improved material printing to avoid very long lists of components (:issue:`144`). * Allow querying for materials by components (:issue:`95`). diff --git a/doc/source/conf.py b/doc/source/conf.py index a410895d..cefc22e6 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -68,6 +68,8 @@ # Display the version display_version = True +linkcheck_ignore = ["https://nucleardata.lanl.gov/.*"] + # -- External link configuration --------------------------------------------- UM63 = ( "https://mcnp.lanl.gov/pdf_files/TechReport_2022_LANL_LA-UR-22-30006" diff --git a/doc/source/dev_standards.rst b/doc/source/dev_standards.rst index e2607f8a..3ca9da19 100644 --- a/doc/source/dev_standards.rst +++ b/doc/source/dev_standards.rst @@ -45,6 +45,13 @@ Design Philosophy #. Defer to vanilla python, and only use the standard library. Currently the only dependencies are `numpy `_ and `sly `_. There must be good justification for breaking from this convention and complicating things for the user. +Style Guide +----------- + +#. Thou shall be `PEP 8 `_, and use `black `_. +#. Spaces not tabs with 4 spaces for an indent. +#. External imports before internal imports with a blank line in between. All imports are alphabetized. + Doc Strings ----------- diff --git a/doc/source/developing.rst b/doc/source/developing.rst index 0265bf5f..ab333a49 100644 --- a/doc/source/developing.rst +++ b/doc/source/developing.rst @@ -690,3 +690,18 @@ Users are more like to use this dynamic code. In general this philosophy is: if it's not the source of truth, it should be a generator. +Constants and Meta Data Structures +---------------------------------- + +MontePy uses constants and data structures to utilize meta-programming +and remove redundant code. +Typical constants can be found in :mod:`montepy.constants`. + +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 + 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. diff --git a/doc/source/migrations/migrate0_1.rst b/doc/source/migrations/migrate0_1.rst index 81d4be5d..3a88c327 100644 --- a/doc/source/migrations/migrate0_1.rst +++ b/doc/source/migrations/migrate0_1.rst @@ -21,43 +21,47 @@ and can be advantageous. See :issue:`504` for more details. Due to this it was decided that the best way forward was to abandon the old design, and to create a brand new data structure. -This means that backwards compatibility *will* be broken, -and so this fix is leading to a major version release. +This means that backwards compatibility *was* broken, +and so this fix led to a major version release. Deprecations ------------ -The following properties and objects are currently deprecated, -and will be removed in MontePy 1.0.0. +The following properties and objects are currently deprecated +and were removed in MontePy 1.0.0. -* :func:`montepy.data_inputs.material.Material.material_components`. +* :func:`~montepy.data_inputs.material.Material.material_components`. This is the dictionary that caused this design problem. -* :class:`montepy.data_inputs.material_components.MaterialComponents` - This is the class that stores information in the above dictionary. - It is largely excess object wrapping, that makes the material interface +* :class:`~montepy.data_inputs.material_component.MaterialComponent`: + This was the class that stores information in the above dictionary. + It was largely excess object wrapping that made the material interface overly complex. -* :class:`montepy.data_inputs.Isotope` will be renamed to ``Nuclide``. - This is to better align with MCNP documentation, - and better reflect that the nuclear data for a nuclide can represent +* :class:`~montepy.data_inputs.isotope.Isotope` was renamed to :class:`~montepy.data_inputs.nuclide.Nuclide`. + This is to better align with MCNP documentation + and to better reflect that the nuclear data for a nuclide can represent isotopic, isomeric, or atomic data. New Interface & Migration ------------------------- +For more details, see the new :ref:`mat_tutorial` tutorial in the getting started guide, +as well as the example in the :class:`~montepy.data_inputs.material.Material` documentation. + .. note:: This design is not finalized and is subject to change. This is the currently planned design for ``1.0.0a1``. If you have input you can `join the discussion `_. - This is also where alpha-testing will be announced. + For feedback on the alpha test, please `join this discussion `_. ``material_components`` removal ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Material composition data has moved from ``Material.material_components`` to the ``Material`` itself. +Material composition data has moved from ``Material.material_components`` to the +:class:`~montepy.data_inputs.material.Material` itself. ``Material`` is now a list-like iterable. It is a list of tuples which are ``(nuclide, fraction)`` pairs. @@ -76,37 +80,173 @@ Searching Components ^^^^^^^^^^^^^^^^^^^^ Finding a specific ``Nuclide`` in a ``Material`` is now much easier. -First there will be a ``Material.find`` method that takes either a ``Nuclide`` string, +First, there is a :func:`~montepy.data_inputs.material.Material.find` method that takes either a ``Nuclide`` string, or various over search criteria (e.g., ``element``), 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 ``Material.contains`` function will provide more options, -such as setting a minimum threshold, and testing for multiple nuclides at once. +The :func:`~montepy.data_inputs.material.Material.contains` function will provide more options, +such as setting a minimum threshold and testing for multiple nuclides at once. Adding Nuclides ^^^^^^^^^^^^^^^ -Adding a new nuclide will be easiest with the ``add_nuclide`` function. -Editing Nuclide Compositon -^^^^^^^^^^^^^^^^^^^^^^^^^^ +Adding a new nuclide is easiest with the :func:`~montepy.data_inputs.material.Material.add_nuclide` function. + +Editing Nuclide Composition +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 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. ``Isotope`` Deprecation and Removal ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The decision was made to remove the name ``Isotope``. +The decision was made to remove the name :class:`montepy.data_inputs.isotope.Isotope`. This is because not all material components are an isotope, they may be an isomer, or event an element. -Rather the MCNP generalized terminology of ``Nuclide`` was adopted. +Rather the MCNP generalized terminology of :class:`montepy.data_inputs.nuclide.Nuclide` was adopted. The idea of a specific nuclide, e.g., ``H-1`` was separated from an MCNP material component e.g., ``1001.80c``. -The actual ``Nuclide`` information was moved to a new class: ``Nucleus``, +The actual ``Nuclide`` information was moved to a new class: :class:`~montepy.data_inputs.nuclide.Nucleus` that is immutable. -The ``Nuclide`` wraps this and adds a ``Library`` object to specify the nuclear data that is used. +The :class:`~montepy.data_inputs.nuclide.Nuclide` wraps this and adds a :class:`~montepy.data_inputs.nuclide.Library` object to specify the nuclear data that is used. It makes sense to be able to change a library. It does not make sense to change the intrinsic properties of a nuclide (i.e., ``Z``, ``A``, etc.). + + +Code Comparison between 0.x and 1.x +----------------------------------- + +Here are some example code blocks of various material operations in both versions. + +Iterating over Material Components +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In MontePy 0.x +"""""""""""""" + +.. testcode:: + :skipif: True + + import montepy + problem = montepy.read_input("foo.imcnp") + mat = problem.materials[1] + for component in mat.material_components.values(): + print(component.fraction, component.isotope) + +This would print: + +.. testoutput:: + + 2.0 H-1 (80c) + 1.0 O-16 (80c) + +In MontePy 1.x +"""""""""""""" + +.. testcode:: + + import montepy + problem = montepy.read_input("foo.imcnp") + mat = problem.materials[1] + for nuclide, fraction in mat: + print(fraction, nuclide) + +Would print: + +.. testoutput:: + + 2.0 H-1 (80c) + 1.0 O-16 (80c) + +Adding Material Components +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Appending and editing the material components in a material in MontePy 0.x +was rather clunky. That was a large part of the motivation for this release. + +In MontePy 0.x +"""""""""""""" +.. testcode:: + :skipif: True + + from montepy.data_inputs.isotope import Isotope + from montepy.data_inputs.material_component import MaterialComponent + #construct new isotope + new_isotope = Isotope("5010.80c") + # construct new component + comp = MaterialComponent(new_isotope, 1e-6) + # add actual component to material + mat.material_components[new_isotope] = comp + +In MontePy 1.x +"""""""""""""" + +.. testcode:: + + mat.add_nuclide("B-10.80c", 1e-6) + + +Finding, Editing, and Deleting a Component +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Accessing a specific component is another reason for this release. +As you may have noticed, ``material_components`` is a dictionary with the keys being an ``Isotope``. +Due to a bug in MontePy 0.x, the exact instance of an Isotope must be passed as the key to access that item. + +In MontePy 0.x +"""""""""""""" + +.. testcode:: + :skipif: True + + target_isotope = Isotope("5010.80c") + key = None + for isotope in mat.material_components: + if isotope.element == target_isotope.element and isotope.A == target_isotope.A: + key = isotope + break + # get material component object + comp = mat[key] + # edit it. This will update the material because everything is a pointer + comp.fraction = 2e-6 + # delete the component + del mat[key] + + +In MontePy 1.x +"""""""""""""" + +.. testcode:: + + target_isotope = montepy.Nuclide("B-10.80c") + for comp_idx, (nuc, fraction) in mat.find(target_isotope): + break + # update fraction + mat.values[comp_idx] = 2e-6 + # delete component + del mat[comp_idx] + + + + + + + + + + + + + + + + + diff --git a/doc/source/starting.rst b/doc/source/starting.rst index f0873b28..13aa37bb 100644 --- a/doc/source/starting.rst +++ b/doc/source/starting.rst @@ -439,7 +439,7 @@ Surfaces The most important unsung heroes of an MCNP problem are the surfaces. They may be tedious to work with but you can't get anything done without them. -MCNP supports *alot* of types of surfaces, and all of them are special in their own way. +MCNP supports *a lot* of types of surfaces, and all of them are special in their own way. You can see all the surface types here: :class:`~montepy.surfaces.surface_type.SurfaceType`. By default all surfaces are an instance of :class:`~montepy.surfaces.surface.Surface`. They will always have the properties: ``surface_type``, and ``surface_constants``. @@ -705,7 +705,7 @@ This will completely redefine the cell's geometry. You can also modify the geome fuel_cyl.number = 20 fuel_cyl.radius = 1.20 other_fuel_region = -fuel_cyl - fuel_cell.geometry |= other_fuel_region + fuel_cell.geometry |= other_fuel_region #|| .. warning:: @@ -784,6 +784,344 @@ For example: >>> new_cell.material.number 100 + +.. _mat_tutorial: + +Materials +--------- + +Materials are how the nuclide concentrations in cells are specified. +MontePy has always supported materials, but since version 1.0.0, +the design of the interface has significantly improved. + +Specifying Nuclides +^^^^^^^^^^^^^^^^^^^ + +To specify a material, one needs to be able to specify the nuclides that are contained in it. +This is done through :class:`~montepy.data_inputs.nuclide.Nuclide` objects. +This actually a wrapper of a :class:`~montepy.data_inputs.nuclide.Nucleus` and a :class:`~montepy.data_inputs.nuclide.Library` object. +Users should rarely need to interact with the latter two objects, but it is good to be aware of them. +The general idea is that a ``Nuclide`` instance represents a specific set of ACE data that for a ``Nucleus``, +which represents only a physical nuclide with a given ``Library``. + +The easiest way to specify a Nuclide is by its string name. +MontePy supports all valid MCNP ZAIDs for MCNP 6.2, and MCNP 6.3.0. +See :class:`~montepy.data_inputs.nuclide.Nuclide` for how metastable isomers are handled. +However, ZAIDs (like many things in MCNP) are cumbersome. +Therefore, MontePy also supports its own nuclide names as well, which are meant to be more intuitive. +These are very similar to the names introduced with MCNP 6.3.1 (section 1.2.2): this follows: + +.. code-block:: + + Nn[-A][mS][.library] + +Where: + +* ``Nn`` is the atomic symbol of the nuclide, case insensitive. This is required. +* ``A`` is the atomic mass. Zero-padding is not needed. Optional. +* ``S`` is the metastable isomeric state. Only states 1 - 4 are allowed. Optional. +* ``library`` is the library extension of the nuclide. This only supports MCNP 6.2, 6.3 formatting, i.e., 2 - 3 digits followed by a single letter. Optional. + +The following are all valid ways to specify a nuclide: + +.. doctest:: + + >>> import montepy + >>> montepy.Nuclide("1001.80c") + Nuclide('H-1.80c') + >>> montepy.Nuclide("H-1.80c") + Nuclide('H-1.80c') + >>> montepy.Nuclide("H-1.710nc") + Nuclide('H-1.710nc') + >>> montepy.Nuclide("H") + Nuclide('H-0') + >>> montepy.Nuclide("Co-60m1") + Nuclide('Co-60m1') + >>> montepy.Nuclide("Co") + Nuclide('Co-0') + + +.. note:: + + The new SZAID and Name syntax for nuclides introduced with MCNP 6.3.1 is not currently supported by MontePy. + This support likely will be added soon, but probably not prior to MCNP 6.3.1 being available on RSICC. + + +Working with Material Components +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Iterating over Material Components +"""""""""""""""""""""""""""""""""" + +Materials are list-like iterables of tuples. + +.. testcode:: + + mat = problem.materials[1] + + for comp in mat: + print(comp) + +This shows: + +.. testoutput:: + + (Nuclide('U-235.80c'), 5.0) + (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. + +.. testcode:: + + for nuclide in mat.nuclides: + print(repr(nuclide)) + for fraction in mat.values: + print(fraction) + +shows: + +.. testoutput:: + + Nuclide('U-235.80c') + Nuclide('U-238.80c') + 5.0 + 95.0 + +Updating Components of Materials +"""""""""""""""""""""""""""""""" + +Materials are also list-like in that they are settable by index. +The material must always be set to a tuple of a nuclide and a fraction. + +For instance: + +.. testcode:: + + nuclide = mat[0][0] + 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. +To undo the previous changes: + +.. testcode:: + + mat.values[0] = 5.0 + print(mat[0]) + +This outputs: + +.. testoutput:: + + (Nuclide('U-235.80c'), 5.0) + +Adding Components to a Material +""""""""""""""""""""""""""""""" + +To add components to a material use either +:func:`~montepy.data_inputs.material.Material.add_nuclide`, or +:func:`~montepy.data_inputs.material.Material.append`. +:func:`~montepy.data_inputs.material.Material.add_nuclide` is generally the easier method to use. +It accepts a nuclide or the name of a nuclide, and its fraction. + +.. note:: + + 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`. + +.. testcode:: + + mat.add_nuclide("B-10.80c", 1e-6) + for comp in mat: + print(comp) + +.. testoutput:: + + (Nuclide('U-235.80c'), 5.0) + (Nuclide('U-238.80c'), 95.0) + (Nuclide('B-10.80c'), 1e-06) + + +Libraries +^^^^^^^^^ + +MCNP nuclear data comes pre-packaged in multiple different libraries that come from different nuclear data sources +(e.g., ENDF/B-VIII.0), +at different temperatures, +and for different data needs, e.g., neutron data vs. photo-atomic data. +For more details see `LA-UR-17-20709 `_, or +`LANL's nuclear data libraries `_. + +All :class:`~montepy.data_inputs.nuclide.Nuclide` have a :class:`~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 +:func:`~montepy.data_inputs.material.Material.change_libraries`. + +MCNP has a precedence system for determining which library use in a specific instance. +This precedence order is: + +#. The library specified with the nuclide e.g., ``80c`` in ``1001.80c``. +#. The library specified as default for the material e.g., ``nlib = 80c``. +#. The library specified as default in the default material, ``M0``. +#. The first matching entry in the ``XSDIR`` file. + +.. note:: + + MontePy currently does not support reading an ``XSDIR`` file. It will not provide information for + that final step. + +Which library will be used for a given nuclide, material, and problem can be checked with: +:func:`~montepy.data_inputs.material.Material.get_nuclide_library`. + +.. seealso:: + + * :manual63:`5.6.1` + * :manual62:`108` + + +Finding Materials and Nuclides +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Next, we will cover how to find if + +* a nuclide is in a material +* multiple nuclides are in a material +* a range of nuclides (e.g., transuranics) is in a material +* specific materials are in a problem. + +Check if Nuclide in Material +"""""""""""""""""""""""""""" + +First, you can test if a :class:`~montepy.data_inputs.nuclide.Nuclide` +(or :class:`~montepy.data_inputs.nuclide.Nucleus`, or :class:`~montepy.data_inputs.element.Element`, or ``str``), +is in a material. +This is generally interpreted broadly rather than explicitly. +For instance, if the test nuclide has no library this will match +for all libraries, not just the empty library. +Similarly, an elemental nuclide, e.g., ``H-0``, will match all nuclides based +on the element, not just the elemental nuclide. + +.. doctest:: + + >>> montepy.Nuclide('H-1.80c') in mat + False + >>> montepy.Element(92) in mat + True + >>> "U-235" in mat + True + >>> "U-235.70c" in mat + False + >>> montepy.Nuclide("B-0") in mat + True + +For more complicated checks there is the :func:`~montepy.data_inputs.material.Material.contains`. +This takes a plurality of nuclides as well as a threshold. +This returns ``True`` if and only if the material contains *all* nuclides +with a fraction above the threshold. + +.. doctest:: + + >>> mat.contains("H-1.80c") + False + >>> mat.contains("U-235", "U-238", threshold=1.0) + True + >>> mat.contains("U-235.80c", "B-10") + True + >>> mat.contains("U-235.80c", "B-10", threshold=1e-3) + False + +Finding Nuclides +"""""""""""""""" + +Often you may need to only work a subset of the components in a material. +:func:`~montepy.data_inputs.material.Material.find`. +This returns a Generator of the index of the matching component, and then the component tuple. + +.. testcode:: + + # find all uraium nuclides + for idx, (nuclide, fraction) in mat.find("U"): + print(idx, nuclide, fraction) + +.. testoutput:: + + 0 U-235 (80c) 5.0 + 1 U-238 (80c) 95.0 + +There are also other fancy ways to pass slices, for instance to find all transuranics. +See the examples in :func:`~montepy.data_inputs.material.Material.find` for more details. + +There is a related function as well :func:`~montepy.data_inputs.material.Material.find_vals`, +which accepts the same arguments but only returns the matching fractions. +This is great for instance to calculate the heavy metal fraction of a fuel: + +.. testcode:: + + # get all heavy metal fractions + hm_fraction = sum(mat.find_vals(element=slice(90,None))) # slice is requires an end value to accept a start + print(hm_fraction) + +Shows: + +.. testoutput:: + + 100.0 + +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` +of :class:`~montepy.materials.Materials`. +It takes the same arguments as :func:`~montepy.data_inputs.material.Material.contains` +previously discussed. + +Mixing Materials +^^^^^^^^^^^^^^^^ + +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`. +Note this is a method of ``Materials`` and not ``Material``. + +.. note:: + + Materials can only be combined if they are all atom fraction or mass fraction. + +.. note:: + + The materials being mixed will be normalized prior to mixing (the original materials are unaffected). + +.. testcode:: + + mats = problem.materials + h2o = montepy.Material() + h2o.number = 1 + h2o.add_nuclide("1001.80c", 2.0) + h2o.add_nuclide("8016.80c", 1.0) + + boric_acid = montepy.Material() + boric_acid.number = 2 + for nuclide, fraction in { + "1001.80c": 3.0, + "B-10.80c": 1.0 * 0.189, + "B-11.80c": 1.0 * 0.796, + "O-16.80c": 3.0 + }.items(): + boric_acid.add_nuclide(nuclide, fraction) + + # boric acid concentration + boron_conc = 100e-6 # 100 ppm + borated_water = mats.mix([h2o, boric_acid], [1 - boron_conc, boron_conc]) + Universes --------- diff --git a/montepy/constants.py b/montepy/constants.py index 069691bb..abe1091f 100644 --- a/montepy/constants.py +++ b/montepy/constants.py @@ -37,10 +37,10 @@ Citations: -* 5.1.60 and 6.1.0: Section 2.6.2 of LA-UR-18-20808 -* 6.2.0: Section 1.1.1 of LA-UR-17-29981 -* 6.3.0: Section 3.2.2 of LA-UR-22-30006 -* 6.3.1: Section 3.2.2 of LA-UR-24-24602 +* 5.1.60 and 6.1.0: Section 2.6.2 of `LA-UR-18-20808 `_ +* 6.2.0: Section 1.1.1: :manual62:`13` +* 6.3.0: :manual63:`3.2.2` +* 6.3.1: Section 3.2.2 of `LA-UR-24-24602 `_ """ DEFAULT_VERSION = (6, 3, 0) diff --git a/montepy/input_parser/syntax_node.py b/montepy/input_parser/syntax_node.py index af8d6c78..bdae6f87 100644 --- a/montepy/input_parser/syntax_node.py +++ b/montepy/input_parser/syntax_node.py @@ -730,7 +730,7 @@ def _grab_beginning_comment(self, extra_padding): def __eq__(self, other): if not isinstance(other, (type(self), str)): - raise "PaddingNode can only be compared to PaddingNode or str" + return False if isinstance(other, type(self)): other = other.format() return self.format() == other @@ -1379,9 +1379,7 @@ def _check_if_needs_end_padding(self, value): def __eq__(self, other): if not isinstance(other, (type(self), str, int, float)): - raise TypeError( - f"ValueNode can't be equal to {type(other)} type. {other} given." - ) + return False if isinstance(other, ValueNode): other_val = other.value if self.type != other.type: @@ -1764,9 +1762,7 @@ def remove(self, obj): def __eq__(self, other): if not isinstance(other, (type(self), list)): - raise TypeError( - f"ListNode can only be compared to a ListNode or List. {other} given." - ) + return False if len(self) != len(other): return False for lhs, rhs in zip(self, other): diff --git a/montepy/particle.py b/montepy/particle.py index 6e52f9dd..2c9b6ca7 100644 --- a/montepy/particle.py +++ b/montepy/particle.py @@ -7,7 +7,7 @@ class Particle(str, Enum): """ Supported MCNP supported particles. - Taken from Table 2-2 of LA-UR-17-29981. + Taken from :manual62:`46`. """ NEUTRON = "N" @@ -68,7 +68,7 @@ class LibraryType(str, Enum): .. versionadded:: 1.0.0 - Taken from section of 5.6.1 of LA-UR-22-30006 + Taken from :manual63:`5.6.1`. """ def __new__(cls, value, particle=None): diff --git a/tests/test_syntax_parsing.py b/tests/test_syntax_parsing.py index 67c5e5fa..8d03f7f0 100644 --- a/tests/test_syntax_parsing.py +++ b/tests/test_syntax_parsing.py @@ -361,8 +361,7 @@ def test_value_str(self): def test_value_equality(self): value_node1 = syntax_node.ValueNode("1", int) self.assertTrue(value_node1 == value_node1) - with self.assertRaises(TypeError): - value_node1 == syntax_node.PaddingNode("") + assert not value_node1 == syntax_node.PaddingNode("") value_node2 = syntax_node.ValueNode("2", int) self.assertTrue(value_node1 != value_node2) value_node3 = syntax_node.ValueNode("hi", str) @@ -570,8 +569,7 @@ def test_padding_eq(self): self.assertTrue(pad != " hi ") pad1 = syntax_node.PaddingNode(" ") self.assertTrue(pad == pad1) - with self.assertRaises(TypeError): - pad == 1 + assert not pad == 1 def test_comment_init(self): comment = syntax_node.CommentNode("$ hi") @@ -722,8 +720,7 @@ def test_list_equality(self): list_node1 = syntax_node.ListNode("list") for i in range(20): list_node1.append(syntax_node.ValueNode("1.0", float)) - with self.assertRaises(TypeError): - list_node1 == "hi" + assert not list_node1 == "hi" list2 = [syntax_node.ValueNode("1.0", float)] * 19 self.assertTrue(not list_node1 == list2) list2 = [syntax_node.ValueNode("1.0", float)] * 20