1
1
from abc import ABC , abstractmethod
2
2
from dataclasses import dataclass
3
- from typing import Optional , Sequence
3
+ from typing import Optional , Iterable , TYPE_CHECKING
4
4
5
5
from xtl .automate .priority_system import PrioritySystemType , DefaultPrioritySystem , NicePrioritySystem
6
- from xtl .automate .shells import Shell , DefaultShell , BashShell
6
+ from xtl .automate .shells import Shell , DefaultShell , BashShell , CmdShell , WslShell
7
+
8
+ if TYPE_CHECKING :
9
+ from xtl .config .settings import DependencySettings
7
10
8
11
9
12
@dataclass
@@ -15,7 +18,7 @@ class ComputeSite(ABC):
15
18
16
19
_priority_system : Optional [PrioritySystemType ] = None
17
20
_default_shell : Optional [Shell ] = None
18
- _supported_shells : Sequence [Shell ] | None = None
21
+ _supported_shells : Iterable [Shell ] | None = None
19
22
20
23
@property
21
24
def priority_system (self ):
@@ -38,7 +41,7 @@ def default_shell(self) -> Optional[Shell]:
38
41
return self ._default_shell
39
42
40
43
@property
41
- def supported_shells (self ) -> Sequence [Shell ] | None :
44
+ def supported_shells (self ) -> Iterable [Shell ] | None :
42
45
"""
43
46
The supported shells for this compute site. This is used to validate the shell passed to the BatchFile.
44
47
"""
@@ -53,17 +56,25 @@ def is_valid_shell(self, shell: Shell) -> bool:
53
56
return shell in self .supported_shells
54
57
55
58
@abstractmethod
56
- def load_modules (self , modules : str | Sequence [str ]) -> str :
59
+ def load_modules (self , modules : str | Iterable [str ]) -> str :
57
60
"""
58
61
Generates a command for loading the specified modules on the compute site.
59
62
"""
63
+ # TODO: Remove when refactoring AutoPROCJob
60
64
pass
61
65
62
66
@abstractmethod
63
67
def purge_modules (self ) -> str :
64
68
"""
65
69
Generates a command for purging all loaded modules on the compute site.
66
70
"""
71
+ # TODO: Remove when refactoring AutoPROCJob
72
+ pass
73
+
74
+ @abstractmethod
75
+ def get_preamble (self , dependencies : 'DependencySettings' |
76
+ Iterable ['DependencySettings' ],
77
+ shell : Shell | WslShell = None ) -> list [str ]:
67
78
pass
68
79
69
80
def prepare_command (self , command : str ) -> str :
@@ -80,13 +91,64 @@ def __init__(self):
80
91
assumes that all required executables are available on PATH.
81
92
"""
82
93
self ._priority_system = DefaultPrioritySystem ()
94
+ self ._default_shell = DefaultShell
83
95
84
96
def load_modules (self , modules ) -> str :
85
97
return ''
86
98
87
99
def purge_modules (self ) -> str :
88
100
return ''
89
101
102
+ def get_preamble (self , dependencies : 'DependencySettings' |
103
+ Iterable ['DependencySettings' ],
104
+ shell : Shell | WslShell = None ) -> list [str ]:
105
+ # Returns an empty preamble for the local site, as it assumes that all required
106
+ # executables are available on PATH
107
+ return []
108
+
109
+
110
+ class ModulesSite (ComputeSite ):
111
+ def __init__ (self ):
112
+ self ._default_shell = DefaultShell
113
+ self ._priority_system = DefaultPrioritySystem ()
114
+
115
+ def load_modules (self , modules : str | Iterable [str ]) -> str : ...
116
+
117
+ def purge_modules (self ) -> str : ...
118
+
119
+ @staticmethod
120
+ def _load_modules (modules : Iterable [str ], shell : Shell = None ) -> str :
121
+ cmd = 'module load ' + ' ' .join (modules )
122
+ if shell is CmdShell :
123
+ # For Windows CMD, we need to use 'call' to execute the module commands
124
+ cmd = f'call { cmd } '
125
+ return cmd
126
+
127
+ @staticmethod
128
+ def _purge_modules (shell : Shell = None ) -> str :
129
+ cmd = 'module purge'
130
+ if shell is CmdShell :
131
+ cmd = f'call { cmd } '
132
+ return cmd
133
+
134
+ def get_preamble (self , dependencies : 'DependencySettings' |
135
+ Iterable ['DependencySettings' ],
136
+ shell : Shell | WslShell = None ) -> list [str ]:
137
+ if shell is None :
138
+ shell = self ._default_shell
139
+ if not isinstance (dependencies , Iterable ):
140
+ dependencies = [dependencies ]
141
+
142
+ modules = []
143
+ for dep in dependencies :
144
+ if dep .modules :
145
+ modules .extend (dep .modules )
146
+
147
+ cmds = [self ._purge_modules (shell = shell )]
148
+ if modules :
149
+ cmds .append (self ._load_modules (modules , shell = shell ))
150
+ return cmds
151
+
90
152
91
153
class BiotixHPC (ComputeSite ):
92
154
def __init__ (self ):
@@ -99,13 +161,13 @@ def __init__(self):
99
161
self ._default_shell = BashShell
100
162
self ._supported_shells = [BashShell ]
101
163
102
- def load_modules (self , modules : str | Sequence [str ]) -> str :
164
+ def load_modules (self , modules : str | Iterable [str ]) -> str :
103
165
mods = []
104
166
if isinstance (modules , str ):
105
167
# Check for space-separated modules in a single string
106
168
for mod in modules .split ():
107
169
mods .append (mod )
108
- elif isinstance (modules , Sequence ):
170
+ elif isinstance (modules , Iterable ):
109
171
# Otherwise append each module in the list
110
172
for i , mod in enumerate (modules ):
111
173
if not isinstance (mod , str ):
@@ -122,5 +184,11 @@ def load_modules(self, modules: str | Sequence[str]) -> str:
122
184
def purge_modules (self ) -> str :
123
185
return 'module purge'
124
186
187
+ def get_preamble (self , dependencies : 'DependencySettings' |
188
+ Iterable ['DependencySettings' ],
189
+ shell : Shell | WslShell = None ) -> list [str ]:
190
+ # TODO: Implement this
191
+ return []
192
+
125
193
126
- ComputeSiteType = LocalSite | BiotixHPC
194
+ ComputeSiteType = LocalSite | ModulesSite | BiotixHPC
0 commit comments