richqueue 0.9__tar.gz → 1.0__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: richqueue
3
- Version: 0.9
3
+ Version: 1.0
4
4
  Summary: RichQueue
5
5
  Project-URL: Homepage, https://github.com/mwinokan/RichQueue/issues
6
6
  Project-URL: Bug Tracker, https://github.com/mwinokan/RichQueue/issues
@@ -3,7 +3,7 @@ requires = ["hatchling"]
3
3
  build-backend = "hatchling.build"
4
4
  [project]
5
5
  name = "richqueue"
6
- version = "0.9"
6
+ version = "1.0"
7
7
  authors = [
8
8
  { name = "Max Winokan", email = "max@winokan.com" },
9
9
  ]
@@ -31,3 +31,4 @@ include = [
31
31
 
32
32
  [project.scripts]
33
33
  rq = "richqueue.main:main"
34
+ confucius = "richqueue.wisdom:main"
@@ -0,0 +1,142 @@
1
+ from typer import Typer, Option
2
+ from typing import Optional
3
+ from typing_extensions import Annotated
4
+ from .layout import dual_layout
5
+ from rich.live import Live
6
+ import time
7
+ from .console import console
8
+ from .tools import curry
9
+ from .slurm import (
10
+ get_layout_pair,
11
+ get_node_layout,
12
+ get_hist_layout,
13
+ get_job_layout,
14
+ NotOnClusterError,
15
+ )
16
+
17
+ # set up singletons
18
+ app = Typer()
19
+
20
+
21
+ # main CLI command
22
+ @app.callback(invoke_without_command=True)
23
+ def show(
24
+ user: Annotated[
25
+ str,
26
+ Option(
27
+ "-u",
28
+ "--user",
29
+ help="Query jobs for this user. Use 'all' to see all jobs",
30
+ ),
31
+ ] = None,
32
+ long: Annotated[bool, Option("-v", "--long", help="More detailed output")] = False,
33
+ idle: Annotated[bool, Option("-i", "--idle", help="Show available nodes")] = False,
34
+ loop: Annotated[
35
+ bool, Option("-l", "--loop", help="Show a live-updating screen")
36
+ ] = True,
37
+ hist: Annotated[
38
+ int, Option("-h", "--hist", help="Show historical jobs from the last X weeks")
39
+ ] = None,
40
+ hist_unit: Annotated[
41
+ str,
42
+ Option("-hu", "--hist-unit", help="Show historical jobs from the last X weeks"),
43
+ ] = "weeks",
44
+ job: Annotated[
45
+ int, Option("-j", "--job", help="Show details for a specific job")
46
+ ] = None,
47
+ wisdom: Annotated[
48
+ bool, Option("-w", "--wisdom", help="Show a confucius quote on exit")
49
+ ] = False,
50
+ ):
51
+
52
+ screen = True
53
+ disappear = not screen
54
+
55
+ kwargs = {
56
+ "user": user,
57
+ "long": long,
58
+ "idle": idle,
59
+ "loop": loop,
60
+ "hist": hist,
61
+ "hist_unit": hist_unit,
62
+ "screen": screen,
63
+ "disappear": disappear,
64
+ "job": job,
65
+ }
66
+
67
+ # console.print(kwargs)
68
+
69
+ match (bool(idle), bool(hist), bool(job)):
70
+ case (True, False, False):
71
+ loop = False
72
+ layout_func = get_node_layout
73
+ case (False, True, False):
74
+ loop = False
75
+ layout_func = get_hist_layout
76
+ case (False, False, True):
77
+ layout_func = get_job_layout
78
+ case (False, False, False):
79
+ layout_func = curry(dual_layout, get_layout_pair)
80
+ case _:
81
+ raise Exception("Unsupported CLI options")
82
+
83
+ try:
84
+
85
+ # live updating layout
86
+ if loop:
87
+
88
+ layout = layout_func(**kwargs)
89
+
90
+ with Live(
91
+ layout,
92
+ refresh_per_second=4,
93
+ screen=screen,
94
+ transient=disappear,
95
+ vertical_overflow="visible",
96
+ ) as live:
97
+
98
+ try:
99
+ while True:
100
+ layout = layout_func(**kwargs)
101
+ live.update(layout)
102
+ time.sleep(1)
103
+ except KeyboardInterrupt:
104
+ live.stop()
105
+ if wisdom:
106
+ from .wisdom import print_random_quote
107
+
108
+ print_random_quote()
109
+
110
+ # static layout
111
+ else:
112
+
113
+ layout = layout_func(**kwargs)
114
+ console.print(layout)
115
+
116
+ except NotOnClusterError as e:
117
+ console.print(f"[red bold]{e}[reset]")
118
+
119
+
120
+ @app.command()
121
+ def log(job: Annotated[int, Option(help="Show logs from a specific job")]):
122
+ raise NotImplementedError
123
+
124
+
125
+ @app.command()
126
+ def dir(job: Annotated[int, Option(help="Get job directory")]):
127
+ raise NotImplementedError
128
+
129
+
130
+ @app.command()
131
+ def nickname():
132
+ raise NotImplementedError
133
+
134
+
135
+ # start Typer app
136
+ def main():
137
+ app()
138
+
139
+
140
+ # start Typer app
141
+ if __name__ == "__main__":
142
+ app()
@@ -161,16 +161,7 @@ def get_squeue(
161
161
  payload = json.loads(output[0])
162
162
 
163
163
  except json.JSONDecodeError:
164
- # console.print('[orange1 bold]Warning: using example data')
165
-
166
- if job:
167
- example = "squeue_job.json"
168
- else:
169
- example = "squeue_long.json"
170
-
171
- payload = json.load(
172
- open(Path(__file__).parent.parent / "example_data" / example, "rt")
173
- )
164
+ raise NotOnClusterError("Could not get sinfo JSON. Not on a SLURM cluster?")
174
165
 
175
166
  global METADATA
176
167
 
@@ -237,15 +228,17 @@ def get_sacct(
237
228
  output = process.communicate()
238
229
  payload = json.loads(output[0])
239
230
  except json.JSONDecodeError:
231
+ raise NotOnClusterError("Could not get sacct JSON. Not on a SLURM cluster?")
232
+
240
233
  # console.print('[orange1 bold]Warning: using example data')
241
- if job:
242
- example = "sacct_job.json"
243
- else:
244
- example = "sacct.json"
234
+ # if job:
235
+ # example = "sacct_job.json"
236
+ # else:
237
+ # example = "sacct.json"
245
238
 
246
- payload = json.load(
247
- open(Path(__file__).parent.parent / "example_data" / example, "rt")
248
- )
239
+ # payload = json.load(
240
+ # open(Path(__file__).parent.parent / "example_data" / example, "rt")
241
+ # )
249
242
 
250
243
  global METADATA
251
244
 
@@ -295,9 +288,7 @@ def get_sinfo(**kwargs) -> "pandas.DataFrame":
295
288
  output = process.communicate()
296
289
  payload = json.loads(output[0])
297
290
  except json.JSONDecodeError:
298
- payload = json.load(
299
- open(Path(__file__).parent.parent / "example_data" / "sinfo_N.json", "rt")
300
- )
291
+ raise NotOnClusterError("Could not get sinfo JSON. Not on a SLURM cluster?")
301
292
 
302
293
  global METADATA
303
294
 
@@ -476,3 +467,6 @@ COLUMNS = {
476
467
  "current_working_directory",
477
468
  ],
478
469
  }
470
+
471
+
472
+ class NotOnClusterError(Exception): ...
@@ -317,6 +317,7 @@ RUNNING_JOB_COLUMNS = {
317
317
  "submit_time",
318
318
  "start_time",
319
319
  "run_time",
320
+ "time_limit",
320
321
  "partition",
321
322
  "nodes",
322
323
  "job_state",
@@ -328,6 +329,7 @@ RUNNING_JOB_COLUMNS = {
328
329
  "cpus",
329
330
  "start_time",
330
331
  "run_time",
332
+ "time_limit",
331
333
  "job_state",
332
334
  ],
333
335
  }
@@ -498,7 +500,7 @@ COLUMNS = {
498
500
  "requeue": {"header": "Requeue?", "style": "green_yellow"},
499
501
  "exclusive": {"header": "Exclusive?", "style": "green_yellow"},
500
502
  "time_limit": {
501
- "header": "[underline dodger_blue2]Time Limit",
503
+ "header": "[underline dodger_blue2]Limit",
502
504
  "justify": "right",
503
505
  "style": "dodger_blue2",
504
506
  "no_wrap": True,
@@ -12,6 +12,9 @@ def human_timedelta(delta):
12
12
 
13
13
  bits = []
14
14
 
15
+ if delta.days < 0 or delta.seconds < 0:
16
+ return ""
17
+
15
18
  days = delta.days
16
19
 
17
20
  s = delta.seconds
@@ -0,0 +1,259 @@
1
+
2
+ QUOTES = [
3
+ "DO IT TOMORROW",
4
+ "DO DFT TOMORROW",
5
+ "HOW 'BOUT NAH",
6
+ "STYLE OVER SUBSTANCE",
7
+ "I'M NOT CHINESE",
8
+ "TO DRIVE A TANK\nSIMPLY USE DRUIDRY\nTO TRANSFORM INTO\nA TANK DRIVER",
9
+ "IF THE GAUSSIAN FAILS TWICE\nCONSECUTIVELY, GIVE UP",
10
+ "THE FEWER HOURS YOU WORK ON A FIXED SALARY\nTHE HIGHER YOUR HOURLY PAY", # MW
11
+ "COMP. CHEM IS TEMPORARY.\nCONFUCIUS IS FOREVER",
12
+ "BETTER TO ASK FOR FORGIVENESS THAN PERMISSION",
13
+ "DO YOU THINK I WANT TO BE HERE?",
14
+ "READ THE FUCKING MANUAL",
15
+ "NEVER GIVE A COW\nFREE MILK",
16
+ "FOR BETTER OR FOR WORSE\nI'LL ALWAYS HAVE ANOTHER COFFEE", # MW
17
+ "I'M A BIG PROPONENT FOR HAVING FUN", # MW
18
+ "I WOULDN'T BET MY LIFE ON IT",
19
+ "DEATH DOES NOT PROTECT YOU FROM CRITICISM",
20
+ "SOMETIMES YOU HAVE TO SPEND MONEY TO MAKE MONEY.\n\nSOMETIMES YOU HAVE TO SPEND MONEY TO LOSE MONEY.\n\nONE THING IS FOR CERTAIN, YOU HAVE TO SPEND MONEY.", # Rust Valley Restorers
21
+ "PREMATURE JOB FAILURE IS NOTHING TO BE ASHAMED OF",
22
+ "LOUIE TOLD ME WHAT TO DO\nAND I DID MY BEST TO FUCK IT UP",
23
+ "IT IS IMPOSSIBLE TO REVERSE\nTHE CREATION OF A CAKE",
24
+ "CAKE CAN BE CREATED AND DESTROYED",
25
+ "I CAN HEAR BUT I CAN'T LISTEN",
26
+ "I'M BETTER THAN THE MANUAL",
27
+ "BEFORE TRYING, CONSULT ME",
28
+ "CODE FIRST, THINK LATER",
29
+ "WHEN IN DOUBT, CROSS PRODUCT",
30
+ "CHEMIS[bold]DO[/bold] OR CHEMIS[bold]DON'T[/bold]\nTHERE IS NO CHEMIS[bold]TRY[/bold]",
31
+ "I HATE IT HERE",
32
+ "I DIDN'T SIGN UP FOR THIS",
33
+ "I DON'T UNDERSTAND WHY PEOPLE\nWOULD CHOOSE TO BE A BIOLOGIST",
34
+ "I HATE PAST ME",
35
+ "SOUNDS LIKE A FUTURE ME PROBLEM",
36
+ "I STRUGGLE TO FIND PEACE",
37
+ "I HEREBY CLASSIFY THIS AS A ROYAL BALL ACHE",
38
+ "I'M ALL OUT OF PASSION",
39
+ "WHAT IS A DECIMAL PLACE BETWEEN FRIENDS?",
40
+ "###SPICY###OF COURSE",
41
+ "[dodger_blue2 bold] 🇬🇷 OF COURSE [/bold /dodger_blue2]",
42
+ "ΩΦ KΩΥΡΣΕ",
43
+ "FRENCH? SO YOU'RE EASY TO SATISFY",
44
+ "YOU DON'T WANT TO FINISH TOO EARLY",
45
+ "BOLD AND UNPROVEN",
46
+ "WHERE IS MY GIRAFFE??", # CV
47
+ "THIS IS A HIPPOPOTAMUS",
48
+ "MONOGAMOUS ENTANGLEMENT",
49
+ "INVEST IN A STRAP-ON",
50
+ "###SPICY###FRIZZ OFF", # AC
51
+ "I'M FRIZZED OFF", # AC
52
+ "I'M GONNA GO TO THAT BUS STATION TOMORROW\nAND KICK MIKE'S ASS",
53
+ "STRUGGLING FROM SUCCESS",
54
+ "I'D SHOW YOU MINE;\nBUT I DON'T THINK YOU'D LIKE IT",
55
+ "I'M SEVERAL RAKI'S DEEP",
56
+ "DON'T ASK ME QUESTIONS THAT COULD HAVE CONSEQUENCES",
57
+ "ENORMOUS DRAGON OF FAECES,\nDANCING INSIDE ME", # FB
58
+ "I HAD A CRISIS OF FAITH IN MY RESEARCH,\nBUT THEN I REALISED THAT IT'S FINE",
59
+ "IT DEPENDS",
60
+ "KIND OF A PROOF",
61
+ "THE DEAD CAT CAN BE A RESOURCE",
62
+ "WITH A TALK LIKE THAT YOU CAN EXPECT TO MEET A PERSON\nWHO TOTALLY DISAGREES WITH EVERYTHING YOU SAID.\nYOU WILL FIND THAT PERSON IN ME", # Moritz @ QuEBS 2022
63
+ "MIDNIGHT MEAT",
64
+ "EXISTENCE IS CANCER",
65
+ "IT'S A PITY THEY FOUND A CURE FOR LEPROSY", # QuEBS 2022 Excursion
66
+ "###SPICY###MEOW", # RG
67
+ "DON’T KNOW\nDON’T CARE",
68
+ "INTERESTING TRANSFER DOWN THESE RODS",
69
+ # "DISSEMINATE THROUGHOUT THE UK",
70
+ "DUMPING MY PUMP ON",
71
+ "KINDA TOXIC, BUT DON’T WORRY ABOUT THAT",
72
+ "WHACKING GREAT ABSORBER", # AM
73
+ "I KNOW YOU’RE THEORISTS, AND THIS IS VERY MUDDY",
74
+ "I HAVE A PROPENSITY FOR THE DENSITY", # AB @ QuEBS 2022
75
+ "OH MY [bold]GOODNESS[/bold]", # GF
76
+ "YOU ARE UNDERMINING MY AUTHORITY", # unknown @ QuEBS 2022
77
+ "TO BE WEAK, IS ACTUALLY AN ADVANTAGE ",
78
+ "SPEEDY BOARDING",
79
+ "THE PHILOSOPHICAL SIGNIFICANCE OF POO",
80
+ "THE CAFFEINE IS A MATTER OF LIFE AND DEATH ",
81
+ "IT’S ALMOST CERTAINLY WRONG, BUT FUN",
82
+ "THAT WOULD HAVE BEEN WISE,\nHOWEVER,\nI AM NOT A WISE MAN",
83
+ "THAT MAKES YOU THINK SOFT",
84
+ "I WOULD ARGUE THAT BARE LEGS IS BETTER",
85
+ "ANYTHING IS MICROSCOPIC IF IT’S FAR AWAY ENOUGH",
86
+ "AN ERROR OCCURRED,\nHOW IS THAT EVEN SCIENTIFICALLY POSSIBLE",
87
+ "YOU HEAR THAT?\nTHAT’S A TARDIGRADE",
88
+ "I SEEM TO HAVE LOST CONTROL [OF MY MOUSE]",
89
+ "THERE’S NO ANSWER,\nBY THE WAY",
90
+ "BECAUSE OF SOME PHYSICS ",
91
+ "PSEUDO-WEAK",
92
+ "THESE BALLS ARE JUST REGULAR SHINY", # MW
93
+ "THE LAST COUP KIND OF FIZZLED OUT",
94
+ "I THINK IT’S STRAIGHT SO IT MUST BE ERADICATED",
95
+ "KOBE BEEF IS ALSO FAMOUSLY DEAD COW",
96
+ "I’VE ALSO DECIDED I AM NOT A MORAL PERSON",
97
+ "IT WAS ONLY AN EMPTY THREAT", # JJMF
98
+ "THREATS ARE A PART OF WORKING LIFE", # JJMF
99
+ "WELL THE THREAT WORKED!", # JJMF
100
+ "AN EMPTY THREAT IS STILL A THREAT",
101
+ "WHAT DO YOU THINK I’M SOME SORT OF PEPSI CRACK WHORE?",
102
+ "LOW IMPACT FACTOR?\nI WANT LOW IMPACT ON MY LIFE!",
103
+ "NOT F*CK YO MAMA\n\nF*CK YO-YO MA!",
104
+ "I FORGOT ABOUT THE PASSAGE OF TIME",
105
+ "EVERYTHING IS JUST A BIG WEIRD LIGAND",
106
+ "IT NEEDS TO TASTE GOOD, AND KILL YOU", # CV
107
+ "MY ABILITY TO SEE FUNKINESS REQUIRES EXPERIENCE", # ISQBP 2022
108
+ "HISTIDINE IS A PROBLEM",
109
+ "I HATE THE FACT THAT THEY SPENT SO MUCH TIME ON THESE QUOTES,\nINSTEAD OF IMPROVING THEIR SIMULATION SOFTWARE", # Gromacs
110
+ "BUTTER MUSS SEIN",
111
+ "I DON’T NEED A CONTROL BECAUSE I DON’T HAVE ANY RESULTS",
112
+ "LET THE ANIMAL EAT FIBRE,\nAND THEN EAT THE ANIMAL",
113
+ "THAT’S NOT A SHOT MATE!!",
114
+ "FUCK AROUND AND FIND OUT",
115
+ "♫♬♪[bold]OH MON BEBE[/bold]", # Les Kaira
116
+ "WHY DID TOM CHEATHAM KILL US LAST NIGHT?", # ISQBP 2022
117
+ "NOSE-HOOVER? SO LIKE A COCAINE ADDICT?",
118
+ "YOU CAN SLEEP ON A BANANA",
119
+ "AMBER AND I BROKE UP", # MW
120
+ "WE WENT TOO FAR",
121
+ "THEY GOT JIGGLY PHYSICS?",
122
+ "DO YOU WANT TO SEE MY STUFF JIGGLING?",
123
+ "WE DON’T SEE COLOURS HERE,\nWE JUST SEE BALLS",
124
+ "IN MY OPINION THIS IS EXACTLY\nWHAT IS WRONG WITH SCIENCE",
125
+ "I DIDN’T REALISE YOU WERE A NONCE",
126
+ "I HEARD YOU LIKE FINISHING EARLY",
127
+ "JOIN THE QUANTUM BIOLOGY DISCORD SERVER! #GAMERSRISEUP",
128
+ "WE SHOULD GET SOMETHING VENOMOUS LIKE A PLATYPUS",
129
+ "THERE IS TOO MUCH ON YOUTUBE ABOUT PLATYPUS CUSTARD",
130
+ "I DON'T BELIEVE IN GRANDCHILDREN",
131
+ "WINNING IS NEVER AN OPTION, ONLY REVENGE",
132
+ "FEDERICO’S ALLEYWAY BOUQUET", # MW
133
+ "SENT FROM MY GALAXY",
134
+ " _______\n / 12 \\ \n| | |\n|9 | 3|\n| \\ |\n| |\n \\___6___/\n\nGOOD HEAVENS, LOOK AT THE TIME!",
135
+ "Har🌳-Frick ✝️ ",
136
+ "BRANEURISM\n\nSymptoms:\tlight-headed, delirium,\n\t\tdyslexic, autism,\n\t\t\t\tchicken sounds,\n\t\t\t\tflowcharts\n",
137
+ f" LISTEN TO PHAT BRAHMS\n | \\\n V \\\n EAT KATSU \\ IS IT FRIDAY? ----> WAIT\n | \\ | Yes ^ No |\n V \\ V L-----------\n SPIN MESMERISING SPIN ORB | IS HILLSIDE OPEN? ---> KATSU\n | | | \n V ^ V \n [bold]BRANEURYSM[/bold] | IS YOUNG'S OPEN ---> KATSU\n / \\ | | \n /YES \\ | V\n L NO------->--------| IS MAX IN THE OFFICE?\nKATSU COMA | | Yes \\ No\n ----<---- \\\n END THE DAY\n",
138
+ "I WOULDN’T PAY £100 FOR A WET DREAM,\nFOR £100 I CAN GET A WET REALITY",
139
+ "I KNOW YOUR FUTURE…\n\nBUT I’LL TELL YOU AFTER I GO TO THE LOO",
140
+ "YOU ARE HEADING FOR A SMACK",
141
+ "[bold]F*CK!!! WHY ARE THESE GUYS SUCH *$#@'S?![/bold]\n\n...\n\nI NEED ANOTHER COFFEE, I'M NOT ON EDGE ENOUGH.", # MW
142
+ "RESULTS ARE A SOCIAL CONSTRUCT",
143
+ "AUTISOMANCY",
144
+ "IS A HANGING MAN STANDING ON\nA BOX THAT HE IS HOLDING\nBENEATH HIS FEET A\nPERPETUAL MOTION MACHINE?",
145
+ "HAVE YOU READ KARL MARX'S LATEST TWEET?",
146
+ "WE NEED MORE GAY SCIENCE",
147
+ "IF WE OVERCOME THIS I WILL JERK FROM NOW UNTIL THE NEXT YEAR", # FB
148
+ "DO LOOK A THIEVING STUFFED DOUGHNUT IN THE ASS",
149
+ "YOU'RE NOT HUMAN UNTIL YOU'VE BEEN CITED", # LS
150
+ "TRUE [bold]AND[/bold] FALSE",
151
+ "EINSTEIN? LARGELY A B*TCH",
152
+ "I’M SCARED TO GO TO TEXAS, PEOPLE JUST SHOOTING ME", # MS
153
+ "YOU’RE WRONG WITH THAT, YOU’RE ABSOLUTELY WRONG WITH THAT", # MS, supervisory meeting
154
+ "WE SHOULD GET AN OFFICE DILDO",
155
+ "AIDS SALIVA IS A-OK\nSO YOU CAN GIVE THAT WHISTLE A SUCK",
156
+ "NO ONE EVER SAID NOT TO EAT YELLOW RICE",
157
+ "WALRUSES RAPING PENGUINS FOR REASONS THAT ARE NOT YET CLEAR",
158
+ "THEY NEVER SAID DON'T EAT YELLOW RICE",
159
+ "RUINING PEOPLE'S CAREERS BY KEEPING THEM IN THE SAME PLACE\nJUST BECAUSE I DID", # JAK
160
+ "WHEN I FIRST STARTED LECTURING\nI DID A LOT OF BUM WIGGLING", # JAK
161
+ "I DON'T UNDERSTAND HAVING VALUES",
162
+ "PISS",
163
+ "THAT'S THE ONLY REASON I'M NOT\nEATING YOUR FACE OFF RIGHT NOW",
164
+ "DOUBLE-TEAMED BY GERIATRICS",
165
+ "LIMPINGCHAN",
166
+ "LET'S HAVE A QUICK CHAT?\nI NEED TO VENT SOME ANGER!",
167
+ "THE FRENCHMAN BURNS EASILY",
168
+ "WHY IS THE BROWN ALWAYS CAUSING PROBLEMS",
169
+ "QUANTUM NATIONALISM",
170
+ "THERE IS NO SUCH THING AS TIME",
171
+ "IS OUR BANANA CORRECT?",
172
+ "WOULD YOU RATHER:\n\nWALLACE HAMMERING FOR AN HOUR\n\nOR\n\nA BRIEF AL-QAEDA MOMENT?",
173
+ "THE CONSPIRACY GROWS",
174
+ "YOU'RE LOOKING GUILTIER BY THE SECOND",
175
+ "I HAD TO MAKE SOMETHING, BUT I ONLY DESTROY",
176
+ "QUANTUM CRY FOR HELP",
177
+ "QB SOS",
178
+ "UNFORUNATELY THE JAVA VERSION ON EUREKA IS TOO OLD TO RUN MINECRAFT", # MW
179
+ "NOBODY CARES, ESPECIALLY ME",
180
+ "GEOGRAPHICALLY-CHALLENGED",
181
+ "I GUESS THAT'S ONE GOOD THING ABOUT FASCISTS",
182
+ "TESTICLES HAVE SO MUCH POTENTIAL",
183
+ "WHENEVER IN DOUBT, GIVE LOUIE A SHOUT",
184
+ "IF IN MOGADISHU, TELL LOUIE 'I MISS YOU'",
185
+ "IF YOU'RE IN A PICKLE,\nGIVE LOUIE A TICKLE",
186
+ "DOORS - UNLIKE PEOPLE - CAN BE UNFUCKED", # MW
187
+ "ARE YOU GOING TO GO TO HIS OFFICE, LIFT HIS ARMS UP\nAND GET YOUR FINGERS IN THERE?",
188
+ "I CANNOT RIPEN MY OWN BANANA",
189
+ "I DO BELIEVE!",
190
+ "GREAT MINDS THINK THE SAME JUNK",
191
+ """HI EVERYONE.\nHOW DO YOU KEEP WORKING WITH A COLLABORATOR IF\nYOUR LAST MEETING ENDED WITH YOU SAYING\n\n"SPARE ME THIS USELESS AND AGGRESSIVE RHETORIC,\n'CAUSE I DON'T NEED IT, OR CARE ABOUT IT"?""",
192
+ "LUCKILY SCIENCE AND DFT CALCULATIONS,\nDO NOT CARE ABOUT YOUR IMPRESSION OF THEM", # FB
193
+ "I WAS ONLY DOING AN IMPRESSION OF A NONCE!",
194
+ "I GUESS WE ALL LEAVE AS FLESH",
195
+ "SHOULD I BUY AN END OF LIFE PLANNER FOR MY PHD?", # EN
196
+ "WE NEED MORE MONEY TO\nMAKE STUDENTS SUFFER",
197
+ "I WON'T TELL YOU WHAT TO DO,\nI'LL JUST JUDGE YOU",
198
+ "NO, YOU DO NOT NEED TO STAY IN QB.\nAND YOU MIGHT NOT WANT TO DO SO",
199
+ "SHIT CODE IS THE FIRST STEP TO NOT SHIT CODE", # MW
200
+ "GRANTS MAKE IT RAIN!",
201
+ "YOU CAN'T GET DRUNK ON PISS",
202
+ "CAN'T GET CANCELLED IF YOU'RE NOT FAMOUS",
203
+ "I'M STARTING TO BELIEVE THESE ARE NOT REAL CONFUCIUS QUOTES", # MS
204
+ "WOULD YOU RATHER MAKE LOVE TO AN EYE OR A FOOT?", # unknown @ MMC 2023
205
+ "QUANTUM PHYSICS MEANS THAT\nANYTHING CAN HAPPEN AT ANY TIME,\nFOR NO REASON", # Futurama
206
+ "I WOULD BE SCHLOBBIN ON SOMEONE'S KNOB FOR THAT", # LS
207
+ "THERE IS NO GREAT LOVE, WITHOUT GREAT JEALOUSY", # Futurama
208
+ "THE BAD BOYS WON'T WAIT ALL NIGHT", # MW @ ABC 2023
209
+ "YOU WON'T BELIEVE WHAT THIS OLD ITALIAN MAN PUT IN MY MIND",
210
+ "THERE'S NOTHING NATURAL ABOUT AVERAGING COORDINATES", # ABC 2023
211
+ "ONIONS DON'T HURT ME",
212
+ "THAT WAS BEFORE I DISCOVERED TURKISH MEN", # RG @ ABC 2023
213
+ "ALL COSTS ARE SUBSTANTIAL",
214
+ "ALWAYS A GOOD IDEA TO BLAME THE FRENCH",
215
+ "CHEESE, SEX AND ALIENS", # about a museum in Basel
216
+ "YOU HAVE TO ACCEPT YOUR MISERY",
217
+ "COSTA RICA WAS A SIMULATION WITH THE WRONG FORCE FIELD", # Leandro @ ABC 2023
218
+ "LOW ENTROPY REGION OF NERDS",
219
+ "THANK YOU FOR BEING WILLING", # MW @ ABC 2023
220
+ "HELLO STALKERS, COME TO ME",
221
+ "YOU'RE ALWAYS ON THE RECEIVING END OF THE MOOSE SHAFTING",
222
+ "IT'S A COCKTAIL OF SHIT",
223
+ "F*CK HIM, CARVE YOUR OWN PATH", # LS about Löwdin
224
+ "I AM A STRAIGHT WHITE WHALE",
225
+ "TO KILL A MONKEYBIRD",
226
+ "LAZINESS LEADS TO THE ULTIMATE CREATIVITY",
227
+ "DO YOU KNOW HOW TO READ [bold]FACIAL[/bold] LIPS?",
228
+ "THERE'S TOO MANY BALD BASTARDS",
229
+ "MAYBE YOU'RE THE D&D CHARACTER OF SOMEONE ELSE,\nAND THEY ARE DOING A REALLY BAD JOB",
230
+ "THIS IS NOT AN ACT OF GOD,\nIT IS PITY",
231
+ "FREUD'S THEORY ON GRAPEFRUITING YOUR DAD",
232
+ "NORMALLY IT'S SHIT.\n\nBUT TODAY, IT'S [bold]EXCEPTIONALLY[/bold] SHIT",
233
+ "WHAT ARE THESE REVOLUTIONARY LOOKING FIGURES?\nAH YES, HEXAGONS",
234
+ "IF YOU ABUSE THEM, THEY'LL MOVE",
235
+ "IT'S NOT SEXUAL HARASSMENT, IT'S A COMPLIMENT",
236
+ "NOT A GOOD CRAZY",
237
+ "EVENTUALLY YOU HAVE TO CARE ABOUT [bold]SOMETHING[/bold]",
238
+ "DON'T PUSH THE RIVER", # MW
239
+ "THE DILDO OF CONSEQUENCES RARELY ARRIVES PRE-LUBED", # REDDIT
240
+ "IT'S ALL UNDER CONTROL", # TH
241
+ "THERE IS NO FUN WITHOUT VIOLENCE", # GF
242
+ "AN UBER IS TRANSIENT BUT SWIM TRUNKS ARE FOREVER", # MW
243
+ "IT'S NOT STEALING IF YOU PIONEER SOMETHING", # MW
244
+ "THE SUFFERING IS OPTIONAL",
245
+ "THAT'S THANKS TO LOUIE, AIMEE,\nAND - IT PAINS ME TO SAY IT - GEORGE", # alex jones @ QuEBS 2023
246
+ "HOME IS WHERE YOUR CHEEKS IMPRESS", # MW
247
+ "YOUR NUTS ARE DOING A REAL JOB ON MY THROAT", # MW
248
+ "VICIOUS CIRCLE OF BOLLOCKING", # RL, XChem, Aug 2023
249
+ "CROWDS GATHER TO WITNESS FIRST PANINI ARRIVE IN IRELAND", # Waterford Whispers News
250
+ "BLESSED ARE THE TOASTED SANDWICH MAKERS", # Waterford Whispers News
251
+ "BEEF JESUS DIED FOR OUR SINS", # MW
252
+ "I'M NOT IN A PICKLE, I'M IN A POTENTIAL WELL",
253
+ "THE ELECTRON IDENTITY CRISIS",
254
+ "TOY STORY IS A SOCIAL COMMENTARY ON THE MEASUREMENT PROBLEM",
255
+ "DO YOU THINK SOME STUDENTS JUST AREN'T INTELLIGENT ENOUGH?",
256
+ "YOU DON'T NEED A DEBUGGER\nYOU NEED A PRIEST", # MW
257
+ "IF THE PAPER YOU WANT TO READ DOESN'T EXIST, WRITE IT", # MW
258
+ "THE WORLD IS YOUR HOSTAGE", #
259
+ ]
@@ -1,94 +0,0 @@
1
- from typer import Typer
2
- from .layout import dual_layout
3
- from rich.live import Live
4
- import time
5
- from .console import console
6
- from .tools import curry
7
- from .slurm import get_layout_pair, get_node_layout, get_hist_layout, get_job_layout
8
-
9
- # set up singletons
10
- app = Typer()
11
-
12
- # main CLI command
13
-
14
-
15
- @app.command()
16
- def show(
17
- user: None | str = None,
18
- long: bool = False,
19
- idle: bool = False,
20
- loop: bool = True,
21
- hist: int | None = None,
22
- hist_unit: str = "weeks",
23
- job: int | None = None,
24
- # screen: bool = True,
25
- # disappear: bool = True,
26
- ):
27
-
28
- screen = True
29
- disappear = not screen
30
-
31
- kwargs = {
32
- "user": user,
33
- "long": long,
34
- "idle": idle,
35
- "loop": loop,
36
- "hist": hist,
37
- "hist_unit": hist_unit,
38
- "screen": screen,
39
- "disappear": disappear,
40
- "job": job,
41
- }
42
-
43
- # console.print(kwargs)
44
-
45
- match (bool(idle), bool(hist), bool(job)):
46
- case (True, False, False):
47
- loop = False
48
- layout_func = get_node_layout
49
- case (False, True, False):
50
- loop = False
51
- layout_func = get_hist_layout
52
- case (False, False, True):
53
- layout_func = get_job_layout
54
- case (False, False, False):
55
- layout_func = curry(dual_layout, get_layout_pair)
56
- case _:
57
- raise Exception("Unsupported CLI options")
58
-
59
- # live updating layout
60
- if loop:
61
-
62
- layout = layout_func(**kwargs)
63
-
64
- with Live(
65
- layout,
66
- refresh_per_second=4,
67
- screen=screen,
68
- transient=disappear,
69
- vertical_overflow="visible",
70
- ) as live:
71
-
72
- try:
73
- while True:
74
- layout = layout_func(**kwargs)
75
- live.update(layout)
76
- time.sleep(1)
77
- except KeyboardInterrupt:
78
- live.stop()
79
-
80
- # static layout
81
- else:
82
-
83
- layout = layout_func(**kwargs)
84
- console.print(layout)
85
-
86
-
87
- # start Typer app
88
- def main():
89
- app()
90
-
91
-
92
- # start Typer app
93
- if __name__ == "__main__":
94
- app()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes