Skip to content

Commit fe572c7

Browse files
authored
More doc improvements and other fixes (#306)
* Improved docs + better custom repr * Add __or__, __ror__ and __ior__ to MultiClusterMap * Use from_ptr method when loading single Job/Step/Node
1 parent 0a65047 commit fe572c7

19 files changed

+284
-109
lines changed

CHANGELOG.md

+9-10
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
- Ability to modify Database Jobs
1313
- New classes to interact with the Partition API
14-
- [pyslurm.Partition](https://pyslurm.github.io/23.2/reference/partition/#pyslurm.Partition)
15-
- [pyslurm.Partitions](https://pyslurm.github.io/23.2/reference/partition/#pyslurm.Partitions)
14+
- [pyslurm.Partition][]
15+
- [pyslurm.Partitions][]
1616
- New attributes for a Database Job:
17-
- extra
18-
- failed_node
19-
- Now possible to initialize a [pyslurm.db.Jobs][] collection with existing job
20-
ids or pyslurm.db.Job objects
21-
- Added `as_dict` function to all Collections
17+
- `extra`
18+
- `failed_node`
2219
- Added a new Base Class [MultiClusterMap][pyslurm.xcollections.MultiClusterMap] that some Collections inherit from.
20+
- Added `to_json` function to all Collections
2321

2422
### Fixed
2523

@@ -29,9 +27,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2927
- the Job was older than a day
3028

3129
### Changed
32-
33-
- `JobSearchFilter` has been renamed to `JobFilter`
34-
- Renamed `as_dict` Function of some classes to `to_dict`
30+
31+
- Improved Docs
32+
- Renamed `JobSearchFilter` to [pyslurm.db.JobFilter][]
33+
- Renamed `as_dict` function of some classes to `to_dict`
3534

3635
## [23.2.1](https://github.com/PySlurm/pyslurm/releases/tag/v23.2.1) - 2023-05-18
3736

docs/reference/index.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ The `pyslurm` package is a wrapper around the Slurm C-API
2525
it!
2626

2727

28-
## Functionality already reworked:
28+
## Reworked Classes
2929

3030
* Job API
3131
* [pyslurm.Job][]

pyslurm/core/job/job.pxd

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,10 @@ cdef class Jobs(MultiClusterMap):
6969
"""A [`Multi Cluster`][pyslurm.xcollections.MultiClusterMap] collection of [pyslurm.Job][] objects.
7070
7171
Args:
72-
jobs (Union[list, dict], optional=None):
72+
jobs (Union[list[int], dict[int, pyslurm.Job], str], optional=None):
7373
Jobs to initialize this collection with.
7474
frozen (bool, optional=False):
75-
Control whether this collection is "frozen" when reloading Job
75+
Control whether this collection is `frozen` when reloading Job
7676
information.
7777
7878
Attributes:

pyslurm/core/job/job.pyx

+14-5
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,14 @@ cdef class Jobs(MultiClusterMap):
8989
9090
Raises:
9191
RPCError: When getting all the Jobs from the slurmctld failed.
92+
93+
Examples:
94+
>>> import pyslurm
95+
>>> jobs = pyslurm.Jobs.load()
96+
>>> print(jobs)
97+
pyslurm.Jobs({1: pyslurm.Job(1), 2: pyslurm.Job(2)})
98+
>>> print(jobs[1])
99+
pyslurm.Job(1)
92100
"""
93101
cdef:
94102
dict passwd = {}
@@ -134,6 +142,9 @@ cdef class Jobs(MultiClusterMap):
134142
def reload(self):
135143
"""Reload the information for jobs in a collection.
136144
145+
Returns:
146+
(pyslurm.Partitions): Returns self
147+
137148
Raises:
138149
RPCError: When getting the Jobs from the slurmctld failed.
139150
"""
@@ -203,7 +214,7 @@ cdef class Job:
203214
self._dealloc_impl()
204215

205216
def __repr__(self):
206-
return f'{self.__class__.__name__}({self.id})'
217+
return f'pyslurm.{self.__class__.__name__}({self.id})'
207218

208219
@staticmethod
209220
def load(job_id):
@@ -233,15 +244,13 @@ cdef class Job:
233244
"""
234245
cdef:
235246
job_info_msg_t *info = NULL
236-
Job wrap = Job.__new__(Job)
247+
Job wrap = None
237248

238249
try:
239250
verify_rpc(slurm_load_job(&info, job_id, slurm.SHOW_DETAIL))
240251

241252
if info and info.record_count:
242-
# Copy info
243-
wrap._alloc_impl()
244-
memcpy(wrap.ptr, &info.job_array[0], sizeof(slurm_job_info_t))
253+
wrap = Job.from_ptr(&info.job_array[0])
245254
info.record_count = 0
246255

247256
if not slurm.IS_JOB_PENDING(wrap.ptr):

pyslurm/core/job/step.pyx

+15-5
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ cdef class JobSteps(dict):
5959
elif steps is not None:
6060
raise TypeError("Invalid Type: {type(steps)}")
6161

62+
def __repr__(self):
63+
data = super().__repr__()
64+
return f'pyslurm.{self.__class__.__name__}({data})'
65+
6266
@staticmethod
6367
def load(job):
6468
"""Load the Job Steps from the system.
@@ -69,6 +73,14 @@ cdef class JobSteps(dict):
6973
7074
Returns:
7175
(pyslurm.JobSteps): JobSteps of the Job
76+
77+
Examples:
78+
>>> import pyslurm
79+
>>> steps = pyslurm.JobSteps.load(1)
80+
>>> print(steps)
81+
pyslurm.JobSteps({'batch': pyslurm.JobStep('batch')})
82+
>>> print(steps[1])
83+
pyslurm.JobStep('batch')
7284
"""
7385
cdef:
7486
Job _job
@@ -187,7 +199,7 @@ cdef class JobStep:
187199
JobStep.__dict__[name].__set__(self, val)
188200

189201
def __repr__(self):
190-
return f'{self.__class__.__name__}({self.id})'
202+
return f'pyslurm.{self.__class__.__name__}({self.id})'
191203

192204
@staticmethod
193205
def load(job_id, step_id):
@@ -214,17 +226,15 @@ cdef class JobStep:
214226
"""
215227
cdef:
216228
job_step_info_response_msg_t *info = NULL
217-
JobStep wrap = JobStep.__new__(JobStep)
229+
JobStep wrap = None
218230

219231
job_id = job_id.id if isinstance(job_id, Job) else job_id
220232
rc = slurm_get_job_steps(<time_t>0, job_id, dehumanize_step_id(step_id),
221233
&info, slurm.SHOW_ALL)
222234
verify_rpc(rc)
223235

224236
if info and info.job_step_count == 1:
225-
# Copy new info
226-
wrap._alloc_impl()
227-
memcpy(wrap.ptr, &info.job_steps[0], sizeof(job_step_info_t))
237+
wrap = JobStep.from_ptr(&info.job_steps[0])
228238
info.job_step_count = 0
229239
slurm_free_job_step_info_response_msg(info)
230240
else:

pyslurm/core/job/submission.pxd

+3-3
Original file line numberDiff line numberDiff line change
@@ -495,9 +495,9 @@ cdef class JobSubmitDescription:
495495
standard_in (str):
496496
Path to a File acting as standard_in for the batch-script.
497497
This is the same as -i/--input from sbatch.
498-
standard_in (str):
499-
Path to a File acting as standard_in for the batch-script.
500-
This is the same as -i/--input from sbatch.
498+
standard_error (str):
499+
Path to a File acting as standard_error for the batch-script.
500+
This is the same as -e/--error from sbatch.
501501
standard_output (str):
502502
Path to a File to write the Jobs standard_output.
503503
This is the same as -o/--output from sbatch.

pyslurm/core/job/submission.pyx

+12-6
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ cdef class JobSubmitDescription:
7373

7474
slurm_init_job_desc_msg(self.ptr)
7575

76+
def __repr__(self):
77+
return f'pyslurm.{self.__class__.__name__}'
78+
7679
def submit(self):
7780
"""Submit a batch job description.
7881
@@ -87,9 +90,12 @@ cdef class JobSubmitDescription:
8790
>>> desc = pyslurm.JobSubmitDescription(
8891
... name="test-job",
8992
... cpus_per_task=1,
90-
... time_limit="10-00:00:00")
93+
... time_limit="10-00:00:00",
94+
... script="/path/to/your/submit_script.sh")
9195
>>>
9296
>>> job_id = desc.submit()
97+
>>> print(job_id)
98+
99
9399
"""
94100
cdef submit_response_msg_t *resp = NULL
95101

@@ -112,9 +118,9 @@ cdef class JobSubmitDescription:
112118
113119
Args:
114120
overwrite (bool):
115-
If set to True, the value from an option found in the
121+
If set to `True`, the value from an option found in the
116122
environment will override the current value of the attribute
117-
in this instance. Default is False
123+
in this instance. Default is `False`
118124
119125
Examples:
120126
Lets consider you want to set the name of the Job, its Account
@@ -141,13 +147,13 @@ cdef class JobSubmitDescription:
141147
self._parse_env(overwrite)
142148

143149
def load_sbatch_options(self, overwrite=False):
144-
"""Load values from #SBATCH options in the batch script.
150+
"""Load values from `#SBATCH` options in the batch script.
145151
146152
Args:
147153
overwrite (bool):
148-
If set to True, the value from an option found in the in the
154+
If set to `True`, the value from an option found in the in the
149155
batch script will override the current value of the attribute
150-
in this instance. Default is False
156+
in this instance. Default is `False`
151157
"""
152158
if not self.script:
153159
raise ValueError("You need to set the 'script' attribute first.")

pyslurm/core/node.pxd

+6-6
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ cdef class Nodes(MultiClusterMap):
6262
"""A [`Multi Cluster`][pyslurm.xcollections.MultiClusterMap] collection of [pyslurm.Node][] objects.
6363
6464
Args:
65-
nodes (Union[list, dict, str], optional=None):
65+
nodes (Union[list[str], dict[str, Node], str], optional=None):
6666
Nodes to initialize this collection with.
6767
6868
Attributes:
@@ -161,8 +161,7 @@ cdef class Node:
161161
free_memory (int):
162162
Free Memory in Mebibytes on the node.
163163
memory_reserved_for_system (int):
164-
Raw Memory in Mebibytes reserved for the System not usable by
165-
Jobs.
164+
Memory in Mebibytes reserved for the System not usable by Jobs.
166165
temporary_disk (int):
167166
Amount of temporary disk space this node has, in Mebibytes.
168167
weight (int):
@@ -210,9 +209,10 @@ cdef class Node:
210209
external_sensors (dict):
211210
External Sensor info for the Node.
212211
The dict returned contains the following information:
213-
* joules_total (int)
214-
* current_watts (int)
215-
* temperature (int)
212+
213+
* `joules_total` (int)
214+
* `current_watts` (int)
215+
* `temperature` (int)
216216
state (str):
217217
State the node is currently in.
218218
next_state (str):

pyslurm/core/node.pyx

+11-6
Original file line numberDiff line numberDiff line change
@@ -121,13 +121,16 @@ cdef class Nodes(MultiClusterMap):
121121
return nodes
122122

123123
def reload(self):
124-
"""Reload the information for nodes in a collection.
124+
"""Reload the information for Nodes in a collection.
125125
126126
!!! note
127127
128128
Only information for nodes which are already in the collection at
129129
the time of calling this method will be reloaded.
130130
131+
Returns:
132+
(pyslurm.Nodes): Returns self
133+
131134
Raises:
132135
RPCError: When getting the Nodes from the slurmctld failed.
133136
"""
@@ -246,7 +249,7 @@ cdef class Node:
246249
Node.__dict__[name].__set__(self, val)
247250

248251
def __repr__(self):
249-
return f'{self.__class__.__name__}({self.name})'
252+
return f'pyslurm.{self.__class__.__name__}({self.name})'
250253

251254
@staticmethod
252255
cdef Node from_ptr(node_info_t *in_ptr):
@@ -271,6 +274,10 @@ cdef class Node:
271274
272275
Implements the slurm_load_node_single RPC.
273276
277+
Args:
278+
name (str):
279+
The name of the Node to load.
280+
274281
Returns:
275282
(pyslurm.Node): Returns a new Node instance.
276283
@@ -285,7 +292,7 @@ cdef class Node:
285292
cdef:
286293
node_info_msg_t *node_info = NULL
287294
partition_info_msg_t *part_info = NULL
288-
Node wrap = Node.__new__(Node)
295+
Node wrap = None
289296

290297
try:
291298
verify_rpc(slurm_load_node_single(&node_info,
@@ -294,9 +301,7 @@ cdef class Node:
294301
slurm_populate_node_partitions(node_info, part_info)
295302

296303
if node_info and node_info.record_count:
297-
# Copy info
298-
wrap._alloc_impl()
299-
memcpy(wrap.info, &node_info.node_array[0], sizeof(node_info_t))
304+
wrap = Node.from_ptr(&node_info.node_array[0])
300305
node_info.record_count = 0
301306
else:
302307
raise RPCError(msg=f"Node '{name}' does not exist")

pyslurm/core/partition.pyx

+1-1
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ cdef class Partition:
186186
self._dealloc_impl()
187187

188188
def __repr__(self):
189-
return f'{self.__class__.__name__}({self.name})'
189+
return f'pyslurm.{self.__class__.__name__}({self.name})'
190190

191191
@staticmethod
192192
cdef Partition from_ptr(partition_info_t *in_ptr):

pyslurm/db/assoc.pyx

+1-1
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ cdef class Association:
206206
slurmdb_init_assoc_rec(self.ptr, 0)
207207

208208
def __repr__(self):
209-
return f'{self.__class__.__name__}({self.id})'
209+
return f'pyslurm.db.{self.__class__.__name__}({self.id})'
210210

211211
@staticmethod
212212
cdef Association from_ptr(slurmdb_assoc_rec_t *in_ptr):

pyslurm/db/connection.pyx

+8
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ cdef class Connection:
4848
def __dealloc__(self):
4949
self.close()
5050

51+
def __repr__(self):
52+
state = "open" if self.is_open else "closed"
53+
return f'pyslurm.db.{self.__class__.__name__} is {state}'
54+
5155
@staticmethod
5256
def open():
5357
"""Open a new connection to the slurmdbd
@@ -61,6 +65,8 @@ cdef class Connection:
6165
Examples:
6266
>>> import pyslurm
6367
>>> connection = pyslurm.db.Connection.open()
68+
>>> print(connection.is_open)
69+
True
6470
"""
6571
cdef Connection conn = Connection.__new__(Connection)
6672
conn.ptr = <void*>slurmdb_connection_get(&conn.flags)
@@ -77,6 +83,8 @@ cdef class Connection:
7783
>>> connection = pyslurm.db.Connection.open()
7884
>>> ...
7985
>>> connection.close()
86+
>>> print(connection.is_open)
87+
False
8088
"""
8189
if self.is_open:
8290
slurmdb_connection_close(&self.ptr)

pyslurm/db/job.pxd

+2-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,8 @@ cdef class Job:
163163
job_id (int, optional=0):
164164
An Integer representing a Job-ID.
165165
cluster (str, optional=None):
166-
Name of the Cluster for this Job.
166+
Name of the Cluster for this Job. Default is the name of the local
167+
Cluster.
167168
168169
Other Parameters:
169170
admin_comment (str):

0 commit comments

Comments
 (0)