kbasic 0.1.16__tar.gz → 0.1.18__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {kbasic-0.1.16 → kbasic-0.1.18}/PKG-INFO +1 -1
- {kbasic-0.1.16 → kbasic-0.1.18}/pyproject.toml +1 -1
- {kbasic-0.1.16 → kbasic-0.1.18}/src/kbasic/Tex.py +3 -3
- {kbasic-0.1.16 → kbasic-0.1.18}/src/kbasic/__init__.py +1 -0
- {kbasic-0.1.16 → kbasic-0.1.18}/src/kbasic/array.py +77 -15
- {kbasic-0.1.16 → kbasic-0.1.18}/src/kbasic/bar.py +4 -4
- {kbasic-0.1.16 → kbasic-0.1.18}/src/kbasic/parsing.py +13 -5
- {kbasic-0.1.16 → kbasic-0.1.18}/src/kbasic/shell.py +51 -19
- {kbasic-0.1.16 → kbasic-0.1.18}/src/kbasic/typing.py +5 -18
- {kbasic-0.1.16 → kbasic-0.1.18}/src/kbasic/user_input.py +14 -13
- {kbasic-0.1.16 → kbasic-0.1.18}/README.md +0 -0
- {kbasic-0.1.16 → kbasic-0.1.18}/src/kbasic/audio/__init__.py +0 -0
- {kbasic-0.1.16 → kbasic-0.1.18}/src/kbasic/audio/lib/Caroline Rose - year of the slug - 01 everything in its right place.wav +0 -0
- {kbasic-0.1.16 → kbasic-0.1.18}/src/kbasic/audio/lib/success.mp3 +0 -0
- {kbasic-0.1.16 → kbasic-0.1.18}/src/kbasic/audio/sound.py +0 -0
- {kbasic-0.1.16 → kbasic-0.1.18}/src/kbasic/environment/Keyan.py +0 -0
- {kbasic-0.1.16 → kbasic-0.1.18}/src/kbasic/environment/__init__.py +0 -0
- {kbasic-0.1.16 → kbasic-0.1.18}/src/kbasic/environment/anvil.py +0 -0
- {kbasic-0.1.16 → kbasic-0.1.18}/src/kbasic/environment/defaultPC.py +0 -0
- {kbasic-0.1.16 → kbasic-0.1.18}/src/kbasic/strings.py +0 -0
- {kbasic-0.1.16 → kbasic-0.1.18}/src/kbasic/vectors.py +0 -0
|
@@ -28,7 +28,7 @@ def texfraction(num) -> str:
|
|
|
28
28
|
# >-|===|> Classes <|===|-<
|
|
29
29
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
30
30
|
class Tex(str):
|
|
31
|
-
def __init__(self, x):
|
|
31
|
+
def __init__(self, x: str) -> None:
|
|
32
32
|
x = x.strip(' $')
|
|
33
33
|
if x[-1]=='\n': x = x[:-1]
|
|
34
34
|
if x[-2:]=='.0': x = x[:-2]
|
|
@@ -42,5 +42,5 @@ class Tex(str):
|
|
|
42
42
|
self.string = fr"{l2t(x)}"
|
|
43
43
|
self.wrap = "$"+self.string+"$"
|
|
44
44
|
|
|
45
|
-
def __repr__(self): return self.string.strip("$")
|
|
46
|
-
def __str__(self): return self.string
|
|
45
|
+
def __repr__(self) -> str: return self.string.strip("$")
|
|
46
|
+
def __str__(self) -> str: return self.string
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
2
2
|
# >-|===|> Imports <|===|-<
|
|
3
3
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
4
|
+
from kbasic.typing import Number, Iterable
|
|
4
5
|
from typing import Callable
|
|
5
|
-
from numpy import ndarray, argmin, any,
|
|
6
|
-
|
|
6
|
+
from numpy import ndarray, argmin, any, all, absolute, hypot, logspace, log10, \
|
|
7
|
+
where, nanmean, nanmin, nanmax, sqrt, linspace, nanstd, array, \
|
|
8
|
+
isnan, isfinite, arange, mgrid, r_, c_, zeros
|
|
9
|
+
from numpy.fft import fftshift, fft2
|
|
7
10
|
from scipy.interpolate import RegularGridInterpolator
|
|
8
11
|
|
|
9
12
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
@@ -15,13 +18,42 @@ from scipy.interpolate import RegularGridInterpolator
|
|
|
15
18
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
16
19
|
# >-|===|> Functions <|===|-<
|
|
17
20
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
18
|
-
def tile(arr:
|
|
19
|
-
"""take an
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
def tile(arr: Iterable) -> ndarray:
|
|
22
|
+
"""take an array and create a 3x3 grid of copies of that array
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
arr (Iterable): the 2D array you want a tiled version
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
ndarray: a 3x3 grid of coppies of arr
|
|
29
|
+
"""
|
|
30
|
+
x = array(arr)
|
|
31
|
+
return r_[c_[x, x, x], c_[x, x, x], c_[x, x, x]]
|
|
32
|
+
def where_closest(arr:ndarray, value: Number):
|
|
33
|
+
"""find the index where arr is closest to the value of x
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
arr (ndarray): the array to search for the index in
|
|
37
|
+
value (Number): the value you want to get close to
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
_type_: _description_
|
|
41
|
+
"""
|
|
42
|
+
return int(argmin(absolute(arr-value)))
|
|
43
|
+
def where_between(arr:ndarray, low: Number, high: Number):
|
|
44
|
+
"""Find the range of indicies where arr is between low and high
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
arr (ndarray): the array to search through
|
|
48
|
+
low (Number): the lower edge of the range (inclusive)
|
|
49
|
+
high (Number): the upper edge of the range (inclusive)
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
ndarray: an array which is True at indices where low<=arr<=high, and False elsewhere
|
|
53
|
+
"""
|
|
54
|
+
return where((arr>=low)&(arr<=high))
|
|
23
55
|
def bin_this(
|
|
24
|
-
x, y,
|
|
56
|
+
x: Iterable, y: Iterable,
|
|
25
57
|
n_bins: int = 50,
|
|
26
58
|
func: Callable = nanmean
|
|
27
59
|
) -> tuple[ndarray]:
|
|
@@ -50,11 +82,18 @@ def bin_this(
|
|
|
50
82
|
return x_binned, y_binned, bin_errors
|
|
51
83
|
def nan_clip(*args):
|
|
52
84
|
"""
|
|
53
|
-
take a series of arrays and only return the indicies where ALL members are
|
|
85
|
+
take a series of arrays and only return the indicies where ALL members are not nan
|
|
54
86
|
"""
|
|
55
87
|
mask = ~any([isnan(a) for a in args], axis=0)
|
|
56
88
|
nanless_args = tuple([array(a)[mask] for a in args])
|
|
57
89
|
return nanless_args
|
|
90
|
+
def only_finite(*args):
|
|
91
|
+
"""
|
|
92
|
+
take a series of arrays and only return the indicies where ALL members are finite
|
|
93
|
+
"""
|
|
94
|
+
mask = all([isfinite(a) for a in args], axis=0)
|
|
95
|
+
nanless_args = tuple([array(a)[mask] for a in args])
|
|
96
|
+
return nanless_args
|
|
58
97
|
def interpolate2d(
|
|
59
98
|
data, factor: int,
|
|
60
99
|
method: str = 'linear',
|
|
@@ -81,9 +120,32 @@ def interpolate2d(
|
|
|
81
120
|
new_grid = mgrid[:Nx:1/factor, :Ny:1/factor].T
|
|
82
121
|
return RegularGridInterpolator(grid, data_repeat, method=method)(new_grid).T
|
|
83
122
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
123
|
+
def kspec(image: ndarray) -> ndarray:
|
|
124
|
+
"""take 2d fft and center k=0 at the center point"""
|
|
125
|
+
return absolute(fftshift(fft2(image) / (1. * image.shape[0] * image.shape[1])))**2
|
|
126
|
+
|
|
127
|
+
def kspec1d(image: ndarray, bins: int = 100, return_bin_edges: bool = False) -> tuple[ndarray, ndarray, ndarray]:
|
|
128
|
+
"""Take a 2d image and turn it into a 1d fft
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
image (ndarray): the array to take the FFT of
|
|
132
|
+
bins (int, optional): number of k bins. Defaults to 100.
|
|
133
|
+
return_bin_edges (bool, optional): if true return the bin edges, not just the k values. Defaults to False.
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
tuple[ndarray, ndarray, ndarray]:
|
|
137
|
+
"""
|
|
138
|
+
k = kspec(image)
|
|
139
|
+
Ny, Nx = image.shape
|
|
140
|
+
kmag = hypot(*mgrid[
|
|
141
|
+
-Ny // 2: Ny // 2,
|
|
142
|
+
-Nx // 2: Nx // 2
|
|
143
|
+
][::-1])
|
|
144
|
+
kmin = nanmin(kmag[kmag != 0])
|
|
145
|
+
kmax = nanmax(kmag)
|
|
146
|
+
kgrid = r_[[0], logspace(log10(3*kmin), log10(kmax), bins)]
|
|
147
|
+
kx = array([nanmean([kgrid[i], kgrid[i+1]]) for i in range(len(kgrid)-1)])
|
|
148
|
+
ks = array([nanmean(k[where((kgrid[i] < kmag) & (kmag < kgrid[i+1]))]) for i in range(len(kgrid)-1)])
|
|
149
|
+
kerr = array([nanstd(in_bin:=k[where((kgrid[i] < kmag) & (kmag < kgrid[i+1]))])/sqrt(len(in_bin)) for i in range(len(kgrid)-1)])
|
|
150
|
+
if not return_bin_edges: return kx, ks, kerr
|
|
151
|
+
return kgrid, kx, ks, kerr
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
2
2
|
# >-|===|> Imports <|===|-<
|
|
3
3
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
4
|
-
from kbasic.typing import Number
|
|
4
|
+
from kbasic.typing import Number, Iterable
|
|
5
5
|
from kbasic.strings import green, yellow, black
|
|
6
6
|
from contextlib import contextmanager
|
|
7
7
|
import inspect
|
|
@@ -18,7 +18,7 @@ from tqdm import tqdm
|
|
|
18
18
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
19
19
|
def bar(
|
|
20
20
|
x: Number, total: Number,
|
|
21
|
-
width: int = 20, border="|", block="▉", color='white'
|
|
21
|
+
width: int = 20, border: str = "|", block: str = "▉", color: str = 'white'
|
|
22
22
|
) -> str:
|
|
23
23
|
"""create a string representing a progress bar set at 100 * x / total % full.
|
|
24
24
|
|
|
@@ -56,13 +56,13 @@ def redirect_to_tqdm():
|
|
|
56
56
|
yield
|
|
57
57
|
finally:
|
|
58
58
|
inspect.builtins.print = old_print
|
|
59
|
-
def progress_bar(iterator, **kwargs):
|
|
59
|
+
def progress_bar(iterator: Iterable, **kwargs):
|
|
60
60
|
"""tqdm with print redirected to tqdm.write
|
|
61
61
|
"""
|
|
62
62
|
with redirect_to_tqdm():
|
|
63
63
|
for x in tqdm(iterator, **kwargs):
|
|
64
64
|
yield x
|
|
65
|
-
def verbose_bar(iterator, verbose, **kwargs):
|
|
65
|
+
def verbose_bar(iterator: Iterable, verbose: bool, **kwargs):
|
|
66
66
|
"""just a progress bar if verbose is true.
|
|
67
67
|
"""
|
|
68
68
|
return progress_bar(iterator, **kwargs) if verbose else iterator
|
|
@@ -9,13 +9,12 @@ from glob import glob
|
|
|
9
9
|
from shutil import copy, move, copytree, rmtree
|
|
10
10
|
from os.path import isdir, isfile, exists, abspath
|
|
11
11
|
from os import system, remove
|
|
12
|
-
from functools import cached_property
|
|
13
12
|
import tomllib
|
|
14
13
|
|
|
15
14
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
16
15
|
# >-|===|> Definitions <|===|-<
|
|
17
16
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
18
|
-
unreadable_file_types = ['gz', 'tar', 'zip']
|
|
17
|
+
unreadable_file_types: list[str] = ['gz', 'tar', 'zip']
|
|
19
18
|
|
|
20
19
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
21
20
|
# >-|===|> Functions <|===|-<
|
|
@@ -27,7 +26,16 @@ def ensure_path(path: str) -> None:
|
|
|
27
26
|
path (str): the path you want to exist
|
|
28
27
|
"""
|
|
29
28
|
system(f"mkdir -p {path}")
|
|
30
|
-
def could_be_path(path: str) -> bool:
|
|
29
|
+
def could_be_path(path: str) -> bool:
|
|
30
|
+
"""determine if this is anywhere close to a valid path
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
path (str): the path (?) to check
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
bool: True if the first two members of the path are valid else False.
|
|
37
|
+
"""
|
|
38
|
+
return isdir('/'.join(path.split('/')[:2]))
|
|
31
39
|
|
|
32
40
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
33
41
|
# >-|===|> Classes <|===|-<
|
|
@@ -141,7 +149,7 @@ class Folder:
|
|
|
141
149
|
return None
|
|
142
150
|
rmtree(self.path)
|
|
143
151
|
|
|
144
|
-
def parse(path: str | list[str]) -> Folder | File:
|
|
152
|
+
def parse(path: str | list[str]) -> Folder | File | list[Folder | File]:
|
|
145
153
|
"""take a path or list of paths and turn them into Folder or File objects as appropriate.
|
|
146
154
|
|
|
147
155
|
Args:
|
|
@@ -151,7 +159,7 @@ def parse(path: str | list[str]) -> Folder | File:
|
|
|
151
159
|
FileNotFoundError: if you can't match path
|
|
152
160
|
|
|
153
161
|
Returns:
|
|
154
|
-
Folder | File: path as a Folder/File.
|
|
162
|
+
Folder | File | list[Folder|File]: path(s) as a Folder/File.
|
|
155
163
|
"""
|
|
156
164
|
match path:
|
|
157
165
|
case str():
|
|
@@ -5,6 +5,7 @@ from kbasic.bar import redirect_to_tqdm
|
|
|
5
5
|
from kbasic.audio import success
|
|
6
6
|
from kbasic.environment import isAnvil
|
|
7
7
|
if isAnvil: from kbasic.environment.anvil import anvil_user
|
|
8
|
+
from typing import Any
|
|
8
9
|
from subprocess import check_output, DEVNULL
|
|
9
10
|
from tqdm import tqdm
|
|
10
11
|
from time import sleep
|
|
@@ -17,22 +18,38 @@ import numpy as np
|
|
|
17
18
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
18
19
|
# >-|===|> Definitions <|===|-<
|
|
19
20
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
20
|
-
bad = ['\x1b[31m', '\x1b[34m', '\x1b[m']
|
|
21
|
-
_USERNAME_ = "x-kgootkin" if not isAnvil else anvil_user
|
|
21
|
+
bad: list[str] = ['\x1b[31m', '\x1b[34m', '\x1b[m']
|
|
22
|
+
_USERNAME_: str = "x-kgootkin" if not isAnvil else anvil_user
|
|
22
23
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
23
24
|
# >-|===|> Functions <|===|-<
|
|
24
25
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
25
|
-
def parse_shell_output(output):
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
26
|
+
def parse_shell_output(output: str | list[str]) -> str | list[str]:
|
|
27
|
+
"""take the output of a shell command and make it nice
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
output (str | list[str]): the output of a shell command
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
str | list[str]: a cleaned version of output
|
|
34
|
+
"""
|
|
35
|
+
match output:
|
|
36
|
+
case str(): return output
|
|
37
|
+
case [x]: return x
|
|
38
|
+
case [x, *_]:
|
|
39
|
+
for i in range(len(output)):
|
|
40
|
+
for b in bad:
|
|
41
|
+
if b in output[i]:
|
|
42
|
+
output[i] = output[i].strip(b)
|
|
43
|
+
return output
|
|
44
|
+
def system(cmd: str) -> str | list[str]:
|
|
45
|
+
"""a version of os.system that actually can return the output
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
cmd (str): the command to give the terminal
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
str | list[str]: the output of the command (cleaned of color tags)
|
|
52
|
+
"""
|
|
36
53
|
command = cmd.split(' ') if type(cmd)==str else cmd
|
|
37
54
|
for i in range(len(command)-1):
|
|
38
55
|
if command[i].startswith('"'):
|
|
@@ -43,11 +60,24 @@ def system(cmd: str):
|
|
|
43
60
|
for j in range(start_quote+1, end_quote+1): del command[j]
|
|
44
61
|
output = parse_shell_output(check_output(command, stderr=DEVNULL).decode().splitlines())
|
|
45
62
|
return output
|
|
46
|
-
def anvil(cmd: str, username=_USERNAME_):
|
|
63
|
+
def anvil(cmd: str, username=_USERNAME_) -> str | list[str]:
|
|
64
|
+
"""Send a shell command to anvil and parse the output
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
cmd (str): the command to send to anvil
|
|
68
|
+
username (str, optional): your anvil username. tries to parse your anvil username by default.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
str | list[str]: the output of the command (cleaned of color tags)
|
|
72
|
+
"""
|
|
47
73
|
output = parse_shell_output(check_output(['ssh', f'{username}@anvil.rcac.purdue.edu', *cmd.split(' ')], stderr=DEVNULL).decode().splitlines())
|
|
48
74
|
return output
|
|
49
|
-
async def anvil_async(cmd: str):
|
|
50
|
-
|
|
75
|
+
async def anvil_async(cmd: str):
|
|
76
|
+
"""Just an asynchronous version of the anvil command"""
|
|
77
|
+
asyncio.to_thread(anvil, cmd)
|
|
78
|
+
def anvil_queue(username=_USERNAME_):
|
|
79
|
+
"""Send a squeue command to anvil to check on your runs"""
|
|
80
|
+
return anvil(f"squeue -u {username}")
|
|
51
81
|
qs = anvil_queue
|
|
52
82
|
|
|
53
83
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
@@ -57,7 +87,7 @@ qs = anvil_queue
|
|
|
57
87
|
# >-|===|> Classes <|===|-<
|
|
58
88
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
59
89
|
class AnvilJob:
|
|
60
|
-
def __init__(self, queue_row: str, sep="DISTINCTSEPERATOR"):
|
|
90
|
+
def __init__(self, queue_row: str, sep="DISTINCTSEPERATOR") -> None:
|
|
61
91
|
self.sep = sep
|
|
62
92
|
[
|
|
63
93
|
jobid, username, account, name, nodes, cpus, time_limit, status, time
|
|
@@ -72,7 +102,7 @@ class AnvilJob:
|
|
|
72
102
|
self.status = str(status)
|
|
73
103
|
self.time = str(time)
|
|
74
104
|
|
|
75
|
-
def __repr__(self): return "-"*30 + f"\n{self.name}: {self.status}\n\t{self.time}/{self.time_limit}"
|
|
105
|
+
def __repr__(self) -> str: return "-"*30 + f"\n{self.name}: {self.status}\n\t{self.time}/{self.time_limit}"
|
|
76
106
|
|
|
77
107
|
# def update(self, input=True, iter=True):
|
|
78
108
|
# match input, iter:
|
|
@@ -85,11 +115,13 @@ class AnvilJob:
|
|
|
85
115
|
# self.input = dHybridRinput(anvil(f"cat /anvil/scratch/{self.username}/sims/{self.name}/input/input"))
|
|
86
116
|
# case False, True:
|
|
87
117
|
# self.iter = int(anvil(f"ls /anvil/scratch/{self.username}/sims/{self.name}/Output/Fields/Magnetic/Total/x/")[-1][5:-3])
|
|
88
|
-
def get_anvil_jobs(username=_USERNAME_):
|
|
118
|
+
def get_anvil_jobs(username=_USERNAME_) -> list[AnvilJob]:
|
|
119
|
+
"""Parse the squeue and return AnvilJob objects"""
|
|
89
120
|
q = anvil(f"squeue -u {username}")
|
|
90
121
|
if type(q)==str: return []
|
|
91
122
|
return [AnvilJob(x) for x in q[1:]]
|
|
92
123
|
async def get_anvil_jobs_async(username=_USERNAME_):
|
|
124
|
+
"""Just an asynchronous version of get_anvil_jobs"""
|
|
93
125
|
q = await asyncio.to_thread(anvil, f"squeue -u {username}")
|
|
94
126
|
if type(q)==str: return []
|
|
95
127
|
return [AnvilJob(x) for x in q[1:]]
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
# >-|===|> Imports <|===|-<
|
|
10
10
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
11
11
|
from numpy import ndarray, int8, uint8, int16, uint16, int32, uint32, int64, uint64, float16, float32, float64, longdouble, complex64, complex128, clongdouble
|
|
12
|
-
|
|
12
|
+
from collections.abc import Callable, Iterable
|
|
13
|
+
from typing import Any
|
|
13
14
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
14
15
|
# >-|===|> Types <|===|-<
|
|
15
16
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
@@ -19,20 +20,6 @@ class Number:
|
|
|
19
20
|
float, float16, float32, float64, longdouble,
|
|
20
21
|
complex, complex64, complex128, clongdouble
|
|
21
22
|
]
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
]
|
|
26
|
-
|
|
27
|
-
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
28
|
-
# >-|===|> Definitions <|===|-<
|
|
29
|
-
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
30
|
-
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
31
|
-
# >-|===|> Functions <|===|-<
|
|
32
|
-
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
33
|
-
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
34
|
-
# >-|===|> Decorators <|===|-<
|
|
35
|
-
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
36
|
-
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
37
|
-
# >-|===|> Classes <|===|-<
|
|
38
|
-
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
23
|
+
|
|
24
|
+
def __new__(cls):
|
|
25
|
+
return cls
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
2
2
|
# >-|===|> Imports <|===|-<
|
|
3
3
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
8
|
-
# >-|===|> Definitions <|===|-<
|
|
9
|
-
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
4
|
+
from kbasic.typing import Number
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
10
7
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
11
8
|
# >-|===|> Functions <|===|-<
|
|
12
9
|
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
10
|
+
def parse_user_input(response: str, sep: str = ',') -> Any:
|
|
11
|
+
match response:
|
|
12
|
+
case str(x) if x.isnumeric():
|
|
13
|
+
return Number.apply(response)
|
|
14
|
+
case str(x) if ',' in x:
|
|
15
|
+
return tuple(parse_user_input(xi.strip(), sep=sep) for xi in response.split(sep))
|
|
16
|
+
case _:
|
|
17
|
+
return response.lower().strip()
|
|
13
18
|
def yesno(prompt: str):
|
|
14
19
|
"""
|
|
15
20
|
prompt the user to either reply yes or no
|
|
@@ -33,10 +38,6 @@ def yesno(prompt: str):
|
|
|
33
38
|
raise ValueError("need a response with either y or n in it.")
|
|
34
39
|
|
|
35
40
|
return retry_yesno()
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
40
|
-
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
41
|
-
# >-|===|> Classes <|===|-<
|
|
42
|
-
# !==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==!==
|
|
41
|
+
def interactive_set_attribute(obj: Any, attr: str, default_answer: str = "") -> None:
|
|
42
|
+
res: Any = parse_user_input(input(f"Set a value for {repr(obj)}.{attr}:\n\t"))
|
|
43
|
+
setattr(obj, attr, res)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|