idaholab / MontePy

MontePy is the most user friendly Python library (API) to read, edit, and write MCNP input files.
https://www.montepy.org/
MIT License
32 stars 7 forks source link

Implement MCNP_Problem.write(file_handle) #492

Closed tjlaboss closed 3 months ago

tjlaboss commented 3 months ago

Is your feature request related to a problem? Please describe.

In addition to MCNP_Problem.write_to_file(new_problem), implement MCNP_Problem.write_to_stream(file_stream). Then, users can write to any open file stream, including io.StringIO.

Describe the solution you'd like

class MCNP_Problem:
    def write_to_file(self, str: file_path, bool: overwrite=False):
        """
        Check for existence
        Open the file handle
        Call self.write()`
        Close the file handle

        Also, rename kwarg from "new_problem" to "file_path" or something that
        does not imply that it is another ``MCNP_Problem`` instance.
        """
       . . .

and

class MCNP_Problem:
    def write_to_stream(io.TextIOBase: file_handle):
        """
        Write to an open stream.

        Can allow to fail naturally, or do either of the following checks:
        >>> isinstance(file_handle, io.TextIOBase)
        >>> hasattr(file_handle, "write") and callable(getattr(file_handle, "write"))
        """
        . . .

Describe alternatives you've considered The exact naming is up for discussion. I like fpath instead of file_path and fhandle or fh instead of file_handle.

Maybe MCNP_Problem.write_to_stream() should return something, such as the difference of f.tell() before and after writing in case the user wants to rewind the file (similar to a stream's .write()).

Another alternative is that MCNP_Problem could function more like a stream itself, with its own .read() and .write() methods. This seems unnecessary.

Additional context The .write_to_stream() method would be highly useful in the MontePy integration tests.

MicahGale commented 3 months ago

I was just thinking about this for test cases.

MicahGale commented 3 months ago

So see montepy.input_parser.MCNP_input_file. I think we might want to implement write_to_stream and then also just a write that can decide which method to use under the hood?

I would also be ok with write_to_file just accepting any writeable object.

tjlaboss commented 3 months ago

Something like:


class MCNP_Problem:
    def write(self, destination, overwrite=False):
        if hasattr(destination, "write") and callable(gettattr(destination, "write")):
            return self.write_to_stream(destination)
        elif isinstance(destination, (str, os.PathLike)):
            return self.write_to_file(destination, overwrite)
        else:
            raise TypeError("destination {repr(destination)} does not appear to be a file path or a writable stream.")
tjlaboss commented 3 months ago

That would be nice. Pandas and some other packages do something similar. Really what I don't like is that this checks for the existence of a method called write(), inside a method called write() with a different purpose.

tjlaboss commented 3 months ago

I've opened a crude first pass at #493. Let's discuss before I proceed.