Skip to content

Commit 6963e9e

Browse files
authored
Merge pull request #342 from pyiron/refactor
Refactor interface
2 parents 93f52f7 + ec4f38d commit 6963e9e

14 files changed

+152
-134
lines changed
File renamed without changes.

pysqa/utils/basic.py pysqa/base/config.py

+68-15
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,58 @@
22
from typing import List, Optional, Tuple, Union
33

44
import pandas
5+
import yaml
56
from jinja2 import Template
67
from jinja2.exceptions import TemplateSyntaxError
78

8-
from pysqa.utils.core import QueueAdapterCore
9-
from pysqa.utils.execute import execute_command
10-
from pysqa.utils.queues import Queues
11-
from pysqa.utils.validate import value_error_if_none, value_in_range
9+
from pysqa.base.core import QueueAdapterCore, execute_command
10+
from pysqa.base.validate import check_queue_parameters, value_error_if_none
11+
12+
13+
class Queues(object):
14+
"""
15+
Queues is an abstract class simply to make the list of queues available for auto completion. This is mainly used in
16+
interactive environments like jupyter.
17+
"""
18+
19+
def __init__(self, list_of_queues: List[str]):
20+
"""
21+
Initialize the Queues object.
22+
23+
Args:
24+
list_of_queues (List[str]): A list of queue names.
25+
26+
"""
27+
self._list_of_queues = list_of_queues
28+
29+
def __getattr__(self, item: str) -> str:
30+
"""
31+
Get the queue name.
32+
33+
Args:
34+
item (str): The name of the queue.
35+
36+
Returns:
37+
str: The name of the queue.
38+
39+
Raises:
40+
AttributeError: If the queue name is not in the list of queues.
41+
42+
"""
43+
if item in self._list_of_queues:
44+
return item
45+
else:
46+
raise AttributeError
47+
48+
def __dir__(self) -> List[str]:
49+
"""
50+
Get the list of queues.
51+
52+
Returns:
53+
List[str]: The list of queues.
54+
55+
"""
56+
return self._list_of_queues
1257

1358

1459
class QueueAdapterWithConfig(QueueAdapterCore):
@@ -162,18 +207,12 @@ def check_queue_parameters(
162207
"""
163208
if active_queue is None:
164209
active_queue = self._config["queues"][queue]
165-
cores = value_in_range(
166-
value=cores,
167-
value_min=active_queue["cores_min"],
168-
value_max=active_queue["cores_max"],
169-
)
170-
run_time_max = value_in_range(
171-
value=run_time_max, value_max=active_queue["run_time_max"]
172-
)
173-
memory_max = value_in_range(
174-
value=memory_max, value_max=active_queue["memory_max"]
210+
return check_queue_parameters(
211+
active_queue=active_queue,
212+
cores=cores,
213+
run_time_max=run_time_max,
214+
memory_max=memory_max,
175215
)
176-
return cores, run_time_max, memory_max
177216

178217
def _job_submission_template(
179218
self,
@@ -270,3 +309,17 @@ def _load_templates(queue_lst_dict: dict, directory: str = ".") -> None:
270309
+ error.message,
271310
lineno=error.lineno,
272311
)
312+
313+
314+
def read_config(file_name: str = "queue.yaml") -> dict:
315+
"""
316+
Read and parse a YAML configuration file.
317+
318+
Args:
319+
file_name (str): The name of the YAML file to read.
320+
321+
Returns:
322+
dict: The parsed configuration as a dictionary.
323+
"""
324+
with open(file_name, "r") as f:
325+
return yaml.load(f, Loader=yaml.FullLoader)

pysqa/utils/core.py pysqa/base/core.py

+41-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import getpass
22
import importlib
33
import os
4+
import subprocess
45
from typing import List, Optional, Tuple, Union
56

67
import pandas
78
from jinja2 import Template
89

9-
from pysqa.utils.execute import execute_command
1010
from pysqa.wrapper.abstract import SchedulerCommands
1111

1212
queue_type_dict = {
@@ -45,6 +45,46 @@
4545
}
4646

4747

48+
def execute_command(
49+
commands: str,
50+
working_directory: Optional[str] = None,
51+
split_output: bool = True,
52+
shell: bool = False,
53+
error_filename: str = "pysqa.err",
54+
) -> Union[str, List[str]]:
55+
"""
56+
A wrapper around the subprocess.check_output function.
57+
58+
Args:
59+
commands (str): The command(s) to be executed on the command line
60+
working_directory (str, optional): The directory where the command is executed. Defaults to None.
61+
split_output (bool, optional): Boolean flag to split newlines in the output. Defaults to True.
62+
shell (bool, optional): Additional switch to convert commands to a single string. Defaults to False.
63+
error_filename (str, optional): In case the execution fails, the output is written to this file. Defaults to "pysqa.err".
64+
65+
Returns:
66+
Union[str, List[str]]: Output of the shell command either as a string or as a list of strings
67+
"""
68+
if shell and isinstance(commands, list):
69+
commands = " ".join(commands)
70+
try:
71+
out = subprocess.check_output(
72+
commands,
73+
cwd=working_directory,
74+
stderr=subprocess.STDOUT,
75+
universal_newlines=True,
76+
shell=not isinstance(commands, list),
77+
)
78+
except subprocess.CalledProcessError as e:
79+
with open(os.path.join(working_directory, error_filename), "w") as f:
80+
print(e.stdout, file=f)
81+
out = None
82+
if out is not None and split_output:
83+
return out.split("\n")
84+
else:
85+
return out
86+
87+
4888
def get_queue_commands(queue_type: str) -> Union[SchedulerCommands, None]:
4989
"""
5090
Load queuing system commands class

pysqa/utils/validate.py pysqa/base/validate.py

+32-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,36 @@
11
import re
2-
from typing import Union
2+
from typing import Optional, Tuple, Union
3+
4+
5+
def check_queue_parameters(
6+
active_queue: Optional[dict] = None,
7+
cores: int = 1,
8+
run_time_max: Optional[int] = None,
9+
memory_max: Optional[int] = None,
10+
) -> Tuple[Union[float, int, None], Union[float, int, None], Union[float, int, None]]:
11+
"""
12+
Check the parameters of a queue.
13+
14+
Args:
15+
16+
cores (int, optional): The number of cores. Defaults to 1.
17+
run_time_max (int, optional): The maximum run time. Defaults to None.
18+
memory_max (int, optional): The maximum memory. Defaults to None.
19+
active_queue (dict, optional): The active queue. Defaults to None.
20+
21+
Returns:
22+
list: A list of queue parameters [cores, run_time_max, memory_max].
23+
"""
24+
cores = value_in_range(
25+
value=cores,
26+
value_min=active_queue["cores_min"],
27+
value_max=active_queue["cores_max"],
28+
)
29+
run_time_max = value_in_range(
30+
value=run_time_max, value_max=active_queue["run_time_max"]
31+
)
32+
memory_max = value_in_range(value=memory_max, value_max=active_queue["memory_max"])
33+
return cores, run_time_max, memory_max
334

435

536
def value_error_if_none(value: str) -> None:

pysqa/cmd.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
import sys
55
from typing import Optional
66

7+
from pysqa.base.core import execute_command
78
from pysqa.queueadapter import QueueAdapter
8-
from pysqa.utils.execute import execute_command
99

1010

1111
def command_line(

pysqa/ext/modular.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
import pandas
44

5-
from pysqa.utils.basic import QueueAdapterWithConfig
6-
from pysqa.utils.execute import execute_command
5+
from pysqa.base.config import QueueAdapterWithConfig
6+
from pysqa.base.core import execute_command
77

88

99
class ModularQueueAdapter(QueueAdapterWithConfig):

pysqa/ext/remote.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
import paramiko
99
from tqdm import tqdm
1010

11-
from pysqa.utils.basic import QueueAdapterWithConfig
12-
from pysqa.utils.execute import execute_command
11+
from pysqa.base.config import QueueAdapterWithConfig
12+
from pysqa.base.core import execute_command
1313

1414

1515
class RemoteQueueAdapter(QueueAdapterWithConfig):

pysqa/queueadapter.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33

44
import pandas
55

6+
from pysqa.base.config import QueueAdapterWithConfig, read_config
7+
from pysqa.base.core import execute_command
68
from pysqa.ext.modular import ModularQueueAdapter
7-
from pysqa.utils.basic import QueueAdapterWithConfig
8-
from pysqa.utils.config import read_config
9-
from pysqa.utils.execute import execute_command
109

1110

1211
class QueueAdapter(object):

pysqa/utils/config.py

-15
This file was deleted.

pysqa/utils/execute.py

-43
This file was deleted.

pysqa/utils/queues.py

-47
This file was deleted.

tests/test_basic.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
import unittest
66
from jinja2.exceptions import TemplateSyntaxError
77
from pysqa import QueueAdapter
8-
from pysqa.utils.basic import QueueAdapterWithConfig
9-
from pysqa.utils.validate import value_in_range
8+
from pysqa.base.config import QueueAdapterWithConfig
9+
from pysqa.base.validate import value_in_range
1010

1111
__author__ = "Jan Janssen"
1212
__copyright__ = "Copyright 2019, Jan Janssen"

tests/test_execute_command.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import os
22
import unittest
3-
from pysqa.utils.execute import execute_command
3+
from pysqa.base.core import execute_command
44

55

66
class TestExecuteCommand(unittest.TestCase):

tests/test_sge.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import unittest
77
import getpass
88
from pysqa import QueueAdapter
9-
from pysqa.utils.validate import value_in_range
9+
from pysqa.base.validate import value_in_range
1010

1111
try:
1212
import defusedxml.ElementTree as ETree

0 commit comments

Comments
 (0)