Skip to content

Commit

Permalink
adds IDF.copy() and IDF.saveas(inplace=True) (#254)
Browse files Browse the repository at this point in the history
  • Loading branch information
Samuel Letellier-Duchesne committed Dec 3, 2021
1 parent 0d51e92 commit 778fbb6
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 4 deletions.
35 changes: 31 additions & 4 deletions archetypal/idfclass/idf.py
Expand Up @@ -3,7 +3,7 @@
Various functions for processing EnergyPlus models and retrieving results in
different forms.
"""

import io
import itertools
import logging as lg
import math
Expand Down Expand Up @@ -333,6 +333,10 @@ def __repr__(self):
body += sim_info
return f"<{body}>"

def __copy__(self):
"""Get a copy of self."""
return self.copy()

@classmethod
def from_example_files(cls, example_name, epw=None, **kwargs):
"""Load an IDF model from the ExampleFiles folder by name.
Expand Down Expand Up @@ -1427,6 +1431,15 @@ def savecopy(self, filename, lineendings="default", encoding="latin-1"):
super(IDF, self).save(filename, lineendings, encoding)
return Path(filename)

def copy(self):
"""Return a copy of self as an in memory IDF.
The copy is a new IDF object with the same parameters and arguments as self
but is not attached to an file. Use IDF.saveas("idfname.idf", inplace=True)
to save the copy to a file inplace. self.idfname will now be idfname.idf
"""
return self.saveas(io.StringIO(""))

def save(self, lineendings="default", encoding="latin-1", **kwargs):
"""Write the IDF model to the text file.
Expand All @@ -1448,7 +1461,9 @@ def save(self, lineendings="default", encoding="latin-1", **kwargs):
log(f"saved '{self.name}' at '{self.idfname}'")
return self

def saveas(self, filename, lineendings="default", encoding="latin-1"):
def saveas(
self, filename, lineendings="default", encoding="latin-1", inplace=False
):
"""Save the IDF model as.
Writes a new text file and load a new instance of the IDF class (new object).
Expand All @@ -1461,6 +1476,8 @@ def saveas(self, filename, lineendings="default", encoding="latin-1"):
the line endings for the current system.
encoding (str): Encoding to use for the saved file. The default is
'latin-1' which is compatible with the EnergyPlus IDFEditor.
inplace (bool): If True, applies the new filename to self directly,
else a new object is returned with the new filename.
Returns:
IDF: A new IDF object based on the new location file.
Expand Down Expand Up @@ -1490,8 +1507,18 @@ def saveas(self, filename, lineendings="default", encoding="latin-1"):
name = Path(name).basename()
else:
name = file.basename()
file.copy(as_idf.simulation_dir / name)
return as_idf
try:
file.copy(as_idf.simulation_dir / name)
except shutil.SameFileError:
# A copy of self would have the same files in the simdir and
# throw an error.
pass
if inplace:
# If inplace, replace content of self with content of as_idf.
self.__dict__.update(as_idf.__dict__)
else:
# return the new object.
return as_idf

def process_results(self):
"""Return the list of processed results.
Expand Down
15 changes: 15 additions & 0 deletions tests/test_idfclass.py
Expand Up @@ -72,6 +72,21 @@ def wont_transition_correctly(self, config):
wf = "tests/input_data/CAN_PQ_Montreal.Intl.AP.716270_CWEC.epw"
yield IDF(file, epw=wf, as_version="8.9.0")

def test_copy_saveas(self, idf_model, tmp_path):
"""Test making a copy of self and two ways of saving as (inplace or not)."""
idf_copy = idf_model.copy() # make a copy of self

assert idf_copy is not idf_model

# assert saveas modifies self inplace.
id_before = id(idf_copy)
idf_copy.saveas(tmp_path / "in.idf", inplace=True)
id_after = id(idf_copy)
assert id_after == id_before

# assert saveas returns another object
assert idf_copy.saveas(tmp_path / "in.idf", inplace=False) is not idf_copy

def test_default_version_none(self):
file = (
"tests/input_data/necb/NECB 2011-FullServiceRestaurant-NECB HDD "
Expand Down

0 comments on commit 778fbb6

Please sign in to comment.