Skip to content

Commit 93ae014

Browse files
authored
Merge pull request #24 from molssi-seamm/dev
Improved naming of loop subdirectories
2 parents 2d48a4a + 05b5623 commit 93ae014

File tree

6 files changed

+57
-14
lines changed

6 files changed

+57
-14
lines changed

.github/workflows/CI.yaml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,6 @@ on:
77
pull_request:
88
branches:
99
- "main"
10-
schedule:
11-
# Run on master by default Sunday morning at 3:30:
12-
# Scheduled workflows run on the latest commit on the default or base branch.
13-
# (from https://help.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events-schedule)
14-
- cron: "30 3 * * 0"
1510

1611
jobs:
1712
ci:

HISTORY.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
=======
22
History
33
=======
4+
2024.7.28 -- Improved naming of loop subdirectories
5+
* The subdirectories now start at 1, not 0, to make counting more normal
6+
* When looping over systems, now have the option to name the directories
7+
after the system or configuration name, not the iteration number.
8+
49
2023.11.9 -- Bugfix: "For" loops could crash
510
* For loops could crash writing to write final_structure.mmcif before the directory
611
had been made.

loop_step/loop.py

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ def __init__(self, flowchart=None, extension=None):
3838
self._loop_value = None
3939
self._loop_length = None
4040
self._file_handler = None
41+
self._custom_directory_name = None
4142

4243
super().__init__(
4344
flowchart=flowchart, title="Loop", extension=extension, logger=logger
@@ -66,7 +67,11 @@ def git_revision(self):
6667

6768
@property
6869
def working_path(self):
69-
return Path(self.directory) / f"iter_{self._loop_value:{self.iter_format}}"
70+
if self._custom_directory_name is not None:
71+
tmp = Path(self.directory) / self._custom_directory_name
72+
else:
73+
tmp = Path(self.directory) / f"iter_{self._loop_value+1:{self.iter_format}}"
74+
return tmp
7075

7176
def describe(self):
7277
"""Write out information about what this node will do"""
@@ -145,6 +150,9 @@ def run(self):
145150
context=seamm.flowchart_variables._data
146151
)
147152

153+
# Reset variables to initial state.
154+
self._custom_directory_name = None
155+
148156
# Print out header to the main output
149157
printer.important(__(self.description_text(P), indent=self.indent))
150158

@@ -551,6 +559,7 @@ def run(self):
551559
if self._loop_value >= self._loop_length:
552560
self._loop_value = None
553561
self._loop_length = None
562+
self._custom_directory_name = None
554563

555564
# Revert the loop index variables to the next outer loop
556565
# if there is one, or remove them.
@@ -573,6 +582,15 @@ def run(self):
573582
system_db.system = configuration.system
574583
system.configuration = configuration
575584

585+
if P["directory name"] == "system name":
586+
self._custom_directory_name = self.safe_filename(system.name)
587+
elif P["directory name"] == "configuration name":
588+
self._custom_directory_name = self.safe_filename(
589+
configuration.name
590+
)
591+
else:
592+
self._custom_directory_name = None
593+
576594
# Set up the index variables
577595
tmp = self.get_variable("_loop_indices")
578596
self.set_variable(
@@ -605,9 +623,8 @@ def run(self):
605623
# Add the iteration to the ids so the directory structure is
606624
# reasonable
607625
self.flowchart.reset_visited()
608-
self.set_subids(
609-
(*self._id, f"iter_{self._loop_value:{self.iter_format}}")
610-
)
626+
tmp = self.working_path.name
627+
self.set_subids((*self._id, tmp))
611628

612629
# Run through the steps in the loop body
613630
try:
@@ -617,9 +634,8 @@ def run(self):
617634
traceback.print_exc(file=sys.stderr)
618635
traceback.print_exc(file=sys.stdout)
619636
except Exception as e:
620-
printer.job(
621-
f"Caught exception in loop iteration {self._loop_value}: {str(e)}"
622-
)
637+
tmp = self.working_path.name
638+
printer.job(f"Caught exception in loop iteration {tmp}: {str(e)}")
623639
with open(iter_dir / "stderr.out", "a") as fd:
624640
traceback.print_exc(file=fd)
625641
if "continue" in P["errors"]:
@@ -783,3 +799,15 @@ def loop_node(self):
783799
# There is no body of the loop!
784800
self.logger.debug("There is no loop body")
785801
return None
802+
803+
def safe_filename(self, filename):
804+
clean = re.sub(r"[/\\?%*:|\"<>\x7F\x00-\x1F]", "-", filename)
805+
806+
# Check for duplicates...
807+
path = Path(self.directory) / clean
808+
count = 1
809+
while path.exists():
810+
count += 1
811+
path = Path(self.directory) / f"{clean}_{count}"
812+
813+
return path.name

loop_step/loop_parameters.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,19 @@ class LoopParameters(seamm.Parameters):
165165
"description": "",
166166
"help_text": "The filter for the configuration name",
167167
},
168+
"directory name": {
169+
"default": "loop iteration",
170+
"kind": "string",
171+
"default_units": "",
172+
"enumeration": (
173+
"loop iteration",
174+
"system name",
175+
"configuration name",
176+
),
177+
"format_string": "s",
178+
"description": "Directory names:",
179+
"help_text": "The directory name for the loop iteration.",
180+
},
168181
"errors": {
169182
"default": "continue to next iteration",
170183
"kind": "string",

loop_step/tk_loop.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,8 @@ def reset_dialog(self, widget=None):
225225
row=row, column=2, columnspan=2, sticky=tk.EW
226226
)
227227
frame.columnconfigure(3, weight=1)
228+
row += 1
229+
self["directory name"].grid(row=row, column=0, columnspan=3, sticky=tk.W)
228230
else:
229231
raise RuntimeError("Don't recognize the loop_type {}".format(loop_type))
230232
row += 1

versioneer.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -339,9 +339,9 @@ def get_config_from_root(root):
339339
# configparser.NoOptionError (if it lacks "VCS="). See the docstring at
340340
# the top of versioneer.py for instructions on writing your setup.cfg .
341341
setup_cfg = os.path.join(root, "setup.cfg")
342-
parser = configparser.SafeConfigParser()
342+
parser = configparser.ConfigParser()
343343
with open(setup_cfg, "r") as f:
344-
parser.readfp(f)
344+
parser.read_file(f)
345345
VCS = parser.get("versioneer", "VCS") # mandatory
346346

347347
def get(parser, name):

0 commit comments

Comments
 (0)