Repository: idaholab/MontePy

Issue:
Add support for reading from non-file steams
**Is your feature request related to a problem? Please describe.**

It would be nice (mainly in testing) to do:

``` python
fh = io.StringIO()
fh.write(...)
fh.seek(0)
problem = montepy.read_input(fh)
```

**Describe the solution you'd like**
`montepy.read_input` should accept file streams.

**Describe alternatives you've considered**
None that I can think of.

**Additional context**
This is mostly for testing. 

Discussion:

Patch:
diff --git a/doc/source/changelog.rst b/doc/source/changelog.rst
index 86568400..9a219af4 100644
--- a/doc/source/changelog.rst
+++ b/doc/source/changelog.rst
@@ -1,6 +1,13 @@
 MontePy Changelog
 =================
 
+#Next Version#
+--------------
+
+**Bug Fixes**
+
+* Fixed bug where file streams couldn't actually be read (:pull:`553`).
+
 0.4.1
 --------------
 
diff --git a/montepy/input_parser/input_file.py b/montepy/input_parser/input_file.py
index 4e28078d..6184dbe0 100644
--- a/montepy/input_parser/input_file.py
+++ b/montepy/input_parser/input_file.py
@@ -31,6 +31,7 @@ class MCNP_InputFile:
         self._overwrite = overwrite
         self._mode = None
         self._fh = None
+        self._is_stream = False
 
     @classmethod
     def from_open_stream(cls, fh):
@@ -43,6 +44,7 @@ class MCNP_InputFile:
         name = getattr(fh, "name", fh.__class__.__name__)
         inpfile = cls(path=name)
         inpfile._fh = fh
+        inpfile._is_stream = True
         return inpfile
 
     @make_prop_pointer("_path")
@@ -56,7 +58,11 @@ class MCNP_InputFile:
 
     @property
     def name(self):
-        return self.path
+        return self._path
+
+    @property
+    def is_stream(self):
+        return self._is_stream
 
     @make_prop_pointer("_parent_file")
     def parent_file(self):
diff --git a/montepy/input_parser/input_syntax_reader.py b/montepy/input_parser/input_syntax_reader.py
index ac202831..86a7a129 100644
--- a/montepy/input_parser/input_syntax_reader.py
+++ b/montepy/input_parser/input_syntax_reader.py
@@ -38,7 +38,11 @@ def read_input_syntax(input_file, mcnp_version=DEFAULT_VERSION, replace=True):
     """
     global reading_queue
     reading_queue = deque()
-    with input_file.open("r", replace=replace) as fh:
+    if input_file.is_stream:
+        context = input_file
+    else:
+        context = input_file.open("r", replace=replace)
+    with context as fh:
         yield from read_front_matters(fh, mcnp_version)
         yield from read_data(fh, mcnp_version)
 


Test patch:
diff --git a/tests/test_integration.py b/tests/test_integration.py
index b50d0a65..9f25cc6c 100644
--- a/tests/test_integration.py
+++ b/tests/test_integration.py
@@ -1106,10 +1106,12 @@ def test_read_write_cycle(file):
     problem = montepy.read_input(file)
     SKIPPERS = _SKIP_LINES.get(str(file), {})
     fh = io.StringIO()
+    # make string unclosable to keep open after reading.
+    fh.close = lambda: None
     problem.write_problem(fh)
     fh.seek(0)
     # test valid syntax
-    new_problem = montepy.MCNP_Problem("foo")
+    new_problem = montepy.read_input(fh)
     # verify lines are similar
     fh.seek(0)
     lines = [line.rstrip() for line in fh]