Skip to content

Commit 542b410

Browse files
Restore header functionality of 4C input file
Add back functionality to write out information of current application which produces the input file, MeshPy, CubtPy if available Also adds the option to extend the input file with a comment of the application that created the input file
1 parent e897894 commit 542b410

File tree

2 files changed

+101
-90
lines changed

2 files changed

+101
-90
lines changed

src/meshpy/four_c/input_file.py

Lines changed: 100 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,17 @@
2323
4C."""
2424

2525
import copy as _copy
26-
import datetime as _datetime
2726
import os as _os
2827
import shutil as _shutil
2928
import subprocess as _subprocess # nosec B404
3029
import sys as _sys
30+
from datetime import datetime as _datetime
3131
from pathlib import Path as _Path
3232
from typing import Any as _Any
3333
from typing import Dict as _Dict
3434
from typing import List as _List
3535
from typing import Optional as _Optional
36+
from typing import Tuple as _Tuple
3637

3738
import yaml as _yaml
3839

@@ -346,16 +347,25 @@ def delete_section(self, section_name):
346347
raise Warning(f"Section {section_name} does not exist!")
347348

348349
def write_input_file(
349-
self, file_path: _Path, *, nox_xml_file: _Optional[str] = None, **kwargs
350+
self,
351+
file_path: _Path,
352+
*,
353+
nox_xml_file: _Optional[str] = None,
354+
add_application_script: _Optional[bool] = False,
355+
**kwargs,
350356
):
351357
"""Write the input file to disk.
352358
353359
Args:
354-
file_path: str
360+
file_path:
355361
Path to the input file that should be created.
356-
nox_xml_file: str
362+
nox_xml_file:
357363
(optional) If this argument is given, the xml file will be created
358364
with this name, in the same directory as the input file.
365+
add_application_script:
366+
(optional) If this argument is set to True, the script that
367+
created this input file will be added to the input file as a
368+
comment.
359369
"""
360370

361371
# Check if a xml file needs to be written.
@@ -382,22 +392,28 @@ def write_input_file(
382392
width=float("inf"),
383393
)
384394

395+
# Add the application script to the input file.
396+
if add_application_script:
397+
application_path = _Path(_sys.argv[0]).resolve()
398+
application_script_lines = self._get_application_script(
399+
application_path
400+
)
401+
input_file.writelines(application_script_lines)
402+
385403
def get_dict_to_dump(
386404
self,
387405
*,
388-
header: bool = True,
389-
add_script_to_header: bool = True,
406+
information_header: bool = False,
390407
check_nox: bool = True,
391408
):
392409
"""Return the dictionary representation of this input file for dumping
393410
to a yaml file.
394411
395412
Args:
396-
header:
397-
If the header should be exported to the input file files.
398-
add_script_to_header:
399-
If true, a copy of the executing script will be added to the input
400-
file. This is only in affect when header is True.
413+
information_header:
414+
If the information header should be exported to the input file
415+
Contains creation date, git details of MeshPy, CubitPy and
416+
original application which created the input file if available.
401417
check_nox:
402418
If this is true, an error will be thrown if no nox file is set.
403419
"""
@@ -412,14 +428,9 @@ def get_dict_to_dump(
412428
# TODO: Check if the deepcopy makes sense to be optional
413429
yaml_dict = _copy.deepcopy(self.sections)
414430

415-
# TODO: Add header to yaml
416-
# # Add header to the input file.
417-
# end_text = None
418-
419-
# lines.extend(["// " + line for line in _mpy.input_file_meshpy_header])
420-
# if header:
421-
# header_text, end_text = self._get_header(add_script_to_header)
422-
# lines.append(header_text)
431+
# Add information header to the input file
432+
if information_header:
433+
yaml_dict["TITLE"] = self._get_header()
423434

424435
# Check if a file has to be created for the NOX xml information.
425436
if self.nox_xml is not None:
@@ -622,104 +633,104 @@ def get_number_of_coupling_conditions(key):
622633
_dump_mesh_items(yaml_dict, "NODE COORDS", self.nodes)
623634
_dump_mesh_items(yaml_dict, "STRUCTURE ELEMENTS", self.elements)
624635

625-
# TODO: what to do here - how to add the script
626-
# # Add end text.
627-
# if end_text is not None:
628-
# lines.append(end_text)
629-
630636
return yaml_dict
631637

632-
def _get_header(self, add_script):
633-
"""Return the header for the input file."""
638+
def _get_header(self) -> dict:
639+
"""Return the information header for the current MeshPy run.
640+
641+
Returns:
642+
A dictionary with the header information.
643+
"""
644+
645+
def _get_git_data(repo_path: _Path) -> _Tuple[_Optional[str], _Optional[str]]:
646+
"""Return the hash and date of the current git commit.
634647
635-
def get_git_data(repo):
636-
"""Return the hash and date of the current git commit."""
648+
Args:
649+
repo_path: Path to the git repository.
650+
Returns:
651+
A tuple with the hash and date of the current git commit
652+
if available, otherwise None.
653+
"""
637654
git = _shutil.which("git")
638655
if git is None:
639656
raise RuntimeError("Git executable not found")
640657
out_sha = _subprocess.run( # nosec B603
641658
[git, "rev-parse", "HEAD"],
642-
cwd=repo,
659+
cwd=repo_path,
643660
stdout=_subprocess.PIPE,
644661
stderr=_subprocess.DEVNULL,
645662
)
646663
out_date = _subprocess.run( # nosec B603
647664
[git, "show", "-s", "--format=%ci"],
648-
cwd=repo,
665+
cwd=repo_path,
649666
stdout=_subprocess.PIPE,
650667
stderr=_subprocess.DEVNULL,
651668
)
669+
652670
if not out_sha.returncode + out_date.returncode == 0:
653671
return None, None
654-
else:
655-
sha = out_sha.stdout.decode("ascii").strip()
656-
date = out_date.stdout.decode("ascii").strip()
657-
return sha, date
658-
659-
headers = []
660-
end_text = None
661-
662-
# Header containing model information.
663-
current_time_string = _datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
664-
model_header = f"// Date: {current_time_string}\n"
665-
if self.description:
666-
model_header += f"// Description: {self.description}\n"
667-
headers.append(model_header)
668-
669-
# Get information about the script.
670-
script_path = _os.path.realpath(_sys.argv[0])
671-
script_git_sha, script_git_date = get_git_data(_os.path.dirname(script_path))
672-
script_header = "// Script used to create input file:\n"
673-
script_header += f"// path: {script_path}\n"
674-
if script_git_sha is not None:
675-
script_header += (
676-
f"// git sha: {script_git_sha}\n// git date: {script_git_date}\n"
677-
)
678-
headers.append(script_header)
679672

680-
# Header containing meshpy information.
681-
meshpy_git_sha, meshpy_git_date = get_git_data(
682-
_os.path.dirname(_os.path.realpath(__file__))
673+
git_sha = out_sha.stdout.decode("ascii").strip()
674+
git_date = out_date.stdout.decode("ascii").strip()
675+
return git_sha, git_date
676+
677+
header: dict = {"MeshPy": {}}
678+
679+
header["MeshPy"]["creation_date"] = _datetime.now().isoformat(
680+
sep=" ", timespec="seconds"
683681
)
684-
headers.append(
685-
"// Input file created with meshpy\n"
686-
f"// git sha: {meshpy_git_sha}\n"
687-
f"// git date: {meshpy_git_date}\n"
682+
683+
# application which created the input file
684+
application_path = _Path(_sys.argv[0]).resolve()
685+
header["MeshPy"]["Application"] = {"path": str(application_path)}
686+
687+
application_git_sha, application_git_date = _get_git_data(
688+
application_path.parent
688689
)
690+
if application_git_sha is not None and application_git_date is not None:
691+
header["MeshPy"]["Application"] = {
692+
"git_sha": application_git_sha,
693+
"git_date": application_git_date,
694+
}
695+
696+
# MeshPy information
697+
meshpy_git_sha, meshpy_git_date = _get_git_data(
698+
_Path(__file__).resolve().parent
699+
)
700+
if meshpy_git_sha is not None and meshpy_git_date is not None:
701+
header["MeshPy"]["MeshPy"] = {
702+
"git_SHA": meshpy_git_sha,
703+
"git_date": meshpy_git_date,
704+
}
689705

706+
# CubitPy information
690707
if _cubitpy_is_available():
691-
# Get git information about cubitpy.
692-
cubitpy_git_sha, cubitpy_git_date = get_git_data(
708+
cubitpy_git_sha, cubitpy_git_date = _get_git_data(
693709
_os.path.dirname(_cubitpy.__file__)
694710
)
695711

696-
if cubitpy_git_sha is not None:
697-
# Cubitpy_header.
698-
headers.append(
699-
"// The module cubitpy was loaded\n"
700-
f"// git sha: {cubitpy_git_sha}\n"
701-
f"// git date: {cubitpy_git_date}\n"
702-
)
712+
if cubitpy_git_sha is not None and cubitpy_git_date is not None:
713+
header["MeshPy"]["CubitPy"] = {
714+
"git_SHA": cubitpy_git_sha,
715+
"git_date": cubitpy_git_date,
716+
}
717+
718+
return header
703719

704-
string_line = "// " + "".join(["-"] * 80)
720+
def _get_application_script(self, application_path: _Path) -> list[str]:
721+
"""Get the script that created this input file.
705722
706-
# If needed, append the contents of the script.
707-
if add_script:
708-
# Header for the script 'section'.
709-
script_lines = [
710-
string_line
711-
+ "\n// Full script used to create this input file.\n"
712-
+ string_line
713-
+ "\n"
714-
]
723+
Args:
724+
application_path: Path to the script that created this input file.
725+
Returns:
726+
A list of strings with the script that created this input file.
727+
"""
715728

716-
# Get the contents of script.
717-
with open(script_path) as script_file:
718-
script_lines.extend(script_file.readlines())
729+
application_script_lines = [
730+
"# Application script which created this input file:\n"
731+
]
719732

720-
# Comment the python code lines.
721-
end_text = "//".join(script_lines)
733+
with open(application_path) as script_file:
734+
application_script_lines.extend("# " + line for line in script_file)
722735

723-
return (
724-
string_line + "\n" + (string_line + "\n").join(headers) + string_line
725-
), end_text
736+
return application_script_lines

tests/test_four_c_simulation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ def run_four_c_test(tmp_path, name, mesh, n_proc=2, restart=[None, None], **kwar
119119

120120
# Create input file.
121121
input_file = os.path.join(testing_dir, name + ".4C.yaml")
122-
mesh.write_input_file(input_file, add_script_to_header=False, **kwargs)
122+
mesh.write_input_file(input_file, **kwargs)
123123

124124
return_code = run_four_c(
125125
input_file,

0 commit comments

Comments
 (0)