Skip to content

Commit

Permalink
DEV Introduce abstract base class SerpentFile
Browse files Browse the repository at this point in the history
Living in serpentTools/base.py, this class provides a very
basic interface that will begin the transition in separating
file objects and file readers [GH CORE-GATECH-GROUP#335]. Concrete classes must
provide a single class method, ``fromSerpent``, that should perform
the following actions:

1. Accept a string or pathlib.Path object representing the file
   name, or a readable stream to be read
2. Create a new instance of the SerpentFile, e.g. DetectorFile,
3. Process the data in the file or stream, and
4. Return the SerpentFile instance with the new data

A helper function is also provided that can handle this flexibility
in input arguments - serpentTools.base.getStream. Used as a context
manager, this function ensures a readable stream is returned.

Future commits will begin implementing concrete classes piecewise.
  • Loading branch information
drewejohnson committed Dec 29, 2019
1 parent 61f577d commit fba1e33
Showing 1 changed file with 73 additions and 0 deletions.
73 changes: 73 additions & 0 deletions serpentTools/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
from abc import ABC, abstractmethod
from contextlib import contextmanager
from pathlib import Path
import io


class SerpentFile(ABC):
"""Abstract base class for all Serpent files
A specific subclass should be responsible for storing data from
a specific type of file.
"""

@classmethod
@abstractmethod
def fromSerpent(cls, fileOrStream, **kwargs):
"""Return a new instance based on a file or stream
Parameters
----------
fileOrStream : str or pathlib.Path or readable
If a string or :class:`pathlb.Path`, open the file for
reading. Otherwise check that the object can be read by
looking for a ``read`` and ``readline`` method.
kwargs :
Additional key word arguments to be passed to the
actual processing.
Returns
-------
SerpentFile
A serpent file corresponding to the data contained in
the file or readable stream.
"""


@contextmanager
def getStream(fileOrStream):
"""Context manager for coercing an argument to a readable type
Parameters
----------
fileOrStream : str or pathlib.Path or io.TextIOBase
If a string or :class:`pathlib.Path`, open the file
for reading and process. Otherwise, check that the
object can be read by looking for a ``read`` and
``readline`` method.
Yields
------
io.TextIOBase
Some readable stream that will produce either the file
contents, in the case of string or :class:`pathlib.Path`
arguments, or the original input stream
"""
close = True
if isinstance(fileOrStream, Path):
stream = fileOrStream.open("r")
elif isinstance(fileOrStream, str):
stream = open(fileOrStream, "r")
elif not isinstance(fileOrStream, io.TextIOBase):
raise TypeError("{} does not appear to be a readable object "
"or file path".format(type(fileOrStream)))
else:
stream = fileOrStream
close = False
try:
yield stream
finally:
if close:
stream.close()

0 comments on commit fba1e33

Please sign in to comment.