Skip to content

Commit

Permalink
Merge pull request #342 from pyiron/refactor
Browse files Browse the repository at this point in the history
Refactor interface
  • Loading branch information
jan-janssen authored Sep 28, 2024
2 parents 93f52f7 + ec4f38d commit 6963e9e
Show file tree
Hide file tree
Showing 14 changed files with 152 additions and 134 deletions.
File renamed without changes.
83 changes: 68 additions & 15 deletions pysqa/utils/basic.py → pysqa/base/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,58 @@
from typing import List, Optional, Tuple, Union

import pandas
import yaml
from jinja2 import Template
from jinja2.exceptions import TemplateSyntaxError

from pysqa.utils.core import QueueAdapterCore
from pysqa.utils.execute import execute_command
from pysqa.utils.queues import Queues
from pysqa.utils.validate import value_error_if_none, value_in_range
from pysqa.base.core import QueueAdapterCore, execute_command
from pysqa.base.validate import check_queue_parameters, value_error_if_none


class Queues(object):
"""
Queues is an abstract class simply to make the list of queues available for auto completion. This is mainly used in
interactive environments like jupyter.
"""

def __init__(self, list_of_queues: List[str]):
"""
Initialize the Queues object.
Args:
list_of_queues (List[str]): A list of queue names.
"""
self._list_of_queues = list_of_queues

def __getattr__(self, item: str) -> str:
"""
Get the queue name.
Args:
item (str): The name of the queue.
Returns:
str: The name of the queue.
Raises:
AttributeError: If the queue name is not in the list of queues.
"""
if item in self._list_of_queues:
return item
else:
raise AttributeError

def __dir__(self) -> List[str]:
"""
Get the list of queues.
Returns:
List[str]: The list of queues.
"""
return self._list_of_queues


class QueueAdapterWithConfig(QueueAdapterCore):
Expand Down Expand Up @@ -162,18 +207,12 @@ def check_queue_parameters(
"""
if active_queue is None:
active_queue = self._config["queues"][queue]
cores = value_in_range(
value=cores,
value_min=active_queue["cores_min"],
value_max=active_queue["cores_max"],
)
run_time_max = value_in_range(
value=run_time_max, value_max=active_queue["run_time_max"]
)
memory_max = value_in_range(
value=memory_max, value_max=active_queue["memory_max"]
return check_queue_parameters(
active_queue=active_queue,
cores=cores,
run_time_max=run_time_max,
memory_max=memory_max,
)
return cores, run_time_max, memory_max

def _job_submission_template(
self,
Expand Down Expand Up @@ -270,3 +309,17 @@ def _load_templates(queue_lst_dict: dict, directory: str = ".") -> None:
+ error.message,
lineno=error.lineno,
)


def read_config(file_name: str = "queue.yaml") -> dict:
"""
Read and parse a YAML configuration file.
Args:
file_name (str): The name of the YAML file to read.
Returns:
dict: The parsed configuration as a dictionary.
"""
with open(file_name, "r") as f:
return yaml.load(f, Loader=yaml.FullLoader)
42 changes: 41 additions & 1 deletion pysqa/utils/core.py → pysqa/base/core.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import getpass
import importlib
import os
import subprocess
from typing import List, Optional, Tuple, Union

import pandas
from jinja2 import Template

from pysqa.utils.execute import execute_command
from pysqa.wrapper.abstract import SchedulerCommands

queue_type_dict = {
Expand Down Expand Up @@ -45,6 +45,46 @@
}


def execute_command(
commands: str,
working_directory: Optional[str] = None,
split_output: bool = True,
shell: bool = False,
error_filename: str = "pysqa.err",
) -> Union[str, List[str]]:
"""
A wrapper around the subprocess.check_output function.
Args:
commands (str): The command(s) to be executed on the command line
working_directory (str, optional): The directory where the command is executed. Defaults to None.
split_output (bool, optional): Boolean flag to split newlines in the output. Defaults to True.
shell (bool, optional): Additional switch to convert commands to a single string. Defaults to False.
error_filename (str, optional): In case the execution fails, the output is written to this file. Defaults to "pysqa.err".
Returns:
Union[str, List[str]]: Output of the shell command either as a string or as a list of strings
"""
if shell and isinstance(commands, list):
commands = " ".join(commands)
try:
out = subprocess.check_output(
commands,
cwd=working_directory,
stderr=subprocess.STDOUT,
universal_newlines=True,
shell=not isinstance(commands, list),
)
except subprocess.CalledProcessError as e:
with open(os.path.join(working_directory, error_filename), "w") as f:
print(e.stdout, file=f)
out = None
if out is not None and split_output:
return out.split("\n")
else:
return out


def get_queue_commands(queue_type: str) -> Union[SchedulerCommands, None]:
"""
Load queuing system commands class
Expand Down
33 changes: 32 additions & 1 deletion pysqa/utils/validate.py → pysqa/base/validate.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,36 @@
import re
from typing import Union
from typing import Optional, Tuple, Union


def check_queue_parameters(
active_queue: Optional[dict] = None,
cores: int = 1,
run_time_max: Optional[int] = None,
memory_max: Optional[int] = None,
) -> Tuple[Union[float, int, None], Union[float, int, None], Union[float, int, None]]:
"""
Check the parameters of a queue.
Args:
cores (int, optional): The number of cores. Defaults to 1.
run_time_max (int, optional): The maximum run time. Defaults to None.
memory_max (int, optional): The maximum memory. Defaults to None.
active_queue (dict, optional): The active queue. Defaults to None.
Returns:
list: A list of queue parameters [cores, run_time_max, memory_max].
"""
cores = value_in_range(
value=cores,
value_min=active_queue["cores_min"],
value_max=active_queue["cores_max"],
)
run_time_max = value_in_range(
value=run_time_max, value_max=active_queue["run_time_max"]
)
memory_max = value_in_range(value=memory_max, value_max=active_queue["memory_max"])
return cores, run_time_max, memory_max


def value_error_if_none(value: str) -> None:
Expand Down
2 changes: 1 addition & 1 deletion pysqa/cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
import sys
from typing import Optional

from pysqa.base.core import execute_command
from pysqa.queueadapter import QueueAdapter
from pysqa.utils.execute import execute_command


def command_line(
Expand Down
4 changes: 2 additions & 2 deletions pysqa/ext/modular.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import pandas

from pysqa.utils.basic import QueueAdapterWithConfig
from pysqa.utils.execute import execute_command
from pysqa.base.config import QueueAdapterWithConfig
from pysqa.base.core import execute_command


class ModularQueueAdapter(QueueAdapterWithConfig):
Expand Down
4 changes: 2 additions & 2 deletions pysqa/ext/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
import paramiko
from tqdm import tqdm

from pysqa.utils.basic import QueueAdapterWithConfig
from pysqa.utils.execute import execute_command
from pysqa.base.config import QueueAdapterWithConfig
from pysqa.base.core import execute_command


class RemoteQueueAdapter(QueueAdapterWithConfig):
Expand Down
5 changes: 2 additions & 3 deletions pysqa/queueadapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@

import pandas

from pysqa.base.config import QueueAdapterWithConfig, read_config
from pysqa.base.core import execute_command
from pysqa.ext.modular import ModularQueueAdapter
from pysqa.utils.basic import QueueAdapterWithConfig
from pysqa.utils.config import read_config
from pysqa.utils.execute import execute_command


class QueueAdapter(object):
Expand Down
15 changes: 0 additions & 15 deletions pysqa/utils/config.py

This file was deleted.

43 changes: 0 additions & 43 deletions pysqa/utils/execute.py

This file was deleted.

47 changes: 0 additions & 47 deletions pysqa/utils/queues.py

This file was deleted.

4 changes: 2 additions & 2 deletions tests/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import unittest
from jinja2.exceptions import TemplateSyntaxError
from pysqa import QueueAdapter
from pysqa.utils.basic import QueueAdapterWithConfig
from pysqa.utils.validate import value_in_range
from pysqa.base.config import QueueAdapterWithConfig
from pysqa.base.validate import value_in_range

__author__ = "Jan Janssen"
__copyright__ = "Copyright 2019, Jan Janssen"
Expand Down
2 changes: 1 addition & 1 deletion tests/test_execute_command.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import os
import unittest
from pysqa.utils.execute import execute_command
from pysqa.base.core import execute_command


class TestExecuteCommand(unittest.TestCase):
Expand Down
2 changes: 1 addition & 1 deletion tests/test_sge.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import unittest
import getpass
from pysqa import QueueAdapter
from pysqa.utils.validate import value_in_range
from pysqa.base.validate import value_in_range

try:
import defusedxml.ElementTree as ETree
Expand Down

0 comments on commit 6963e9e

Please sign in to comment.