reykit 1.1.25__py3-none-any.whl → 1.1.27__py3-none-any.whl

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.
reykit/rsys.py CHANGED
@@ -10,8 +10,7 @@
10
10
 
11
11
 
12
12
  from typing import Any, TypedDict, Literal, overload
13
- from collections.abc import Callable, Iterable, Sequence, Mapping
14
- from inspect import signature as inspect_signature, _ParameterKind, _empty
13
+ from collections.abc import Iterable, Sequence
15
14
  from sys import path as sys_path, modules as sys_modules
16
15
  from os import getpid as os_getpid
17
16
  from os.path import abspath as os_abspath
@@ -31,14 +30,10 @@ from psutil import (
31
30
  pid_exists as psutil_pid_exists,
32
31
  Process
33
32
  )
34
- from traceback import format_stack, extract_stack
35
- from atexit import register as atexit_register
36
33
  from subprocess import Popen, PIPE
37
34
  from pymem import Pymem
38
35
  from argparse import ArgumentParser
39
- from time import sleep as time_sleep
40
36
  from datetime import datetime
41
- from varname import VarnameRetrievingError, argname
42
37
  from webbrowser import open as webbrowser_open
43
38
  from tkinter.messagebox import (
44
39
  showinfo as tkinter_showinfo,
@@ -56,37 +51,26 @@ from tkinter.filedialog import (
56
51
  askdirectory as tkinter_askdirectory
57
52
  )
58
53
 
59
- from .rexc import throw
60
- from .rtype import RBase, RConfigMeta
54
+ from .rbase import Base, ConfigMeta, throw
61
55
 
62
56
 
63
57
  __all__ = (
64
- 'RConfigSystem',
58
+ 'ConfigSystem',
65
59
  'add_env_path',
66
60
  'reset_env_path',
67
61
  'del_modules',
68
- 'dos_command',
69
- 'dos_command_var',
70
- 'block',
71
- 'at_exit',
72
- 'is_class',
73
- 'is_instance',
74
- 'is_iterable',
75
- 'is_table',
76
- 'is_number_str',
77
- 'get_first_notnull',
78
- 'get_name',
79
- 'get_stack_text',
80
- 'get_stack_param',
81
- 'get_arg_info',
62
+ 'run_cmd',
63
+ 'get_cmd_var',
82
64
  'get_computer_info',
83
65
  'get_network_table',
84
66
  'get_process_table',
85
67
  'search_process',
86
68
  'kill_process',
87
- 'stop_process',
88
- 'start_process',
69
+ 'pause_process',
70
+ 'resume_process',
89
71
  'get_idle_port',
72
+ 'memory_read',
73
+ 'memory_write',
90
74
  'open_browser',
91
75
  'popup_message',
92
76
  'popup_ask',
@@ -127,13 +111,13 @@ NetWorkInfo = TypedDict(
127
111
  ProcessInfo = TypedDict('ProcessInfo', {'create_time': datetime, 'id': int, 'name': str, 'ports': list[int] | None})
128
112
 
129
113
 
130
- class RConfigSystem(RBase, metaclass=RConfigMeta):
114
+ class ConfigSystem(Base, metaclass=ConfigMeta):
131
115
  """
132
- Rey's `config system` type.
116
+ Config system type.
133
117
  """
134
118
 
135
119
  # Added environment path.
136
- _add_env_paths: list[str] = []
120
+ _added_env_paths: list[str] = []
137
121
 
138
122
 
139
123
  def add_env_path(path: str) -> list[str]:
@@ -153,7 +137,7 @@ def add_env_path(path: str) -> list[str]:
153
137
  abs_path = os_abspath(path)
154
138
 
155
139
  # Add.
156
- RConfigSystem._add_env_paths.append(abs_path)
140
+ ConfigSystem._added_env_paths.append(abs_path)
157
141
  sys_path.append(abs_path)
158
142
 
159
143
  return sys_path
@@ -165,9 +149,9 @@ def reset_env_path() -> None:
165
149
  """
166
150
 
167
151
  # Delete.
168
- for path in RConfigSystem._add_env_paths:
152
+ for path in ConfigSystem._added_env_paths:
169
153
  sys_path.remove(path)
170
- RConfigSystem._add_env_paths = []
154
+ ConfigSystem._added_env_paths = []
171
155
 
172
156
 
173
157
  def del_modules(path: str) -> list[str]:
@@ -213,12 +197,12 @@ def del_modules(path: str) -> list[str]:
213
197
 
214
198
 
215
199
  @overload
216
- def dos_command(command: str | Iterable[str], read: Literal[False] = False) -> None: ...
200
+ def run_cmd(command: str | Iterable[str], read: Literal[False] = False) -> None: ...
217
201
 
218
202
  @overload
219
- def dos_command(command: str | Iterable[str], read: Literal[True] = False) -> str: ...
203
+ def run_cmd(command: str | Iterable[str], read: Literal[True]) -> str: ...
220
204
 
221
- def dos_command(command: str | Iterable[str], read: bool = False) -> str | None:
205
+ def run_cmd(command: str | Iterable[str], read: bool = False) -> str | None:
222
206
  """
223
207
  Execute DOS command.
224
208
 
@@ -248,9 +232,9 @@ def dos_command(command: str | Iterable[str], read: bool = False) -> str | None:
248
232
  return output
249
233
 
250
234
 
251
- def dos_command_var(*vars: Any) -> list[Any]:
235
+ def get_cmd_var(*vars: Any) -> list[Any]:
252
236
  """
253
- Use DOS command to input arguments to variables.
237
+ Get DOS command input arguments.
254
238
  Use DOS command `python file --help` to view help information.
255
239
 
256
240
  Parameters
@@ -266,7 +250,7 @@ def dos_command_var(*vars: Any) -> list[Any]:
266
250
  >>> var1 = 1
267
251
  >>> var2 = 2
268
252
  >>> var3 = 3
269
- >>> var1, var2, var3 = dos_command(var1, var2, var3)
253
+ >>> var1, var2, var3 = run_cmd(var1, var2, var3)
270
254
  >>> print(var1, var2, var3)
271
255
  >>> # Use DOS command 'python file.py 10 --var2 20 21'
272
256
  10 [20, 21] 3
@@ -335,457 +319,6 @@ def dos_command_var(*vars: Any) -> list[Any]:
335
319
  return values
336
320
 
337
321
 
338
- def block() -> None:
339
- """
340
- Blocking program, can be double press interrupt to end blocking.
341
- """
342
-
343
- # Start.
344
- print('Start blocking.')
345
- while True:
346
- try:
347
- time_sleep(1)
348
- except KeyboardInterrupt:
349
-
350
- # Confirm.
351
- try:
352
- print('Double press interrupt to end blocking.')
353
- time_sleep(1)
354
-
355
- # End.
356
- except KeyboardInterrupt:
357
- print('End blocking.')
358
- break
359
-
360
- except:
361
- continue
362
-
363
-
364
- def at_exit(*contents: str | Callable | tuple[Callable, Iterable, Mapping]) -> list[Callable]:
365
- """
366
- At exiting print text or execute function.
367
-
368
- Parameters
369
- ----------
370
- contents : execute contents.
371
- - `str`: Define the print text function and execute it.
372
- - `Callable`: Execute function.
373
- - `tuple[Callable, Iterable, Mapping]`: Execute function and position arguments and keyword arguments.
374
-
375
- Returns
376
- -------
377
- Execute functions.
378
- """
379
-
380
- # Register.
381
- funcs = []
382
- for content in reversed(contents):
383
- args = ()
384
- kwargs = {}
385
- if type(content) == str:
386
- func = lambda : print(content)
387
- elif callable(content):
388
- func = content
389
- elif type(content) == tuple:
390
- func, args, kwargs = content
391
- funcs.append(func)
392
- atexit_register(func, *args, **kwargs)
393
- funcs = list(reversed(funcs))
394
-
395
- return funcs
396
-
397
-
398
- def is_class(obj: Any) -> bool:
399
- """
400
- Judge whether it is class.
401
-
402
- Parameters
403
- ----------
404
- obj : Judge object.
405
-
406
- Returns
407
- -------
408
- Judgment result.
409
- """
410
-
411
- # Judge.
412
- judge = isinstance(obj, type)
413
-
414
- return judge
415
-
416
-
417
- def is_instance(obj: Any) -> bool:
418
- """
419
- Judge whether it is instance.
420
-
421
- Parameters
422
- ----------
423
- obj : Judge object.
424
-
425
- Returns
426
- -------
427
- Judgment result.
428
- """
429
-
430
- # judge.
431
- judge = not is_class(obj)
432
-
433
- return judge
434
-
435
-
436
- def is_iterable(
437
- obj: Any,
438
- exclude_types: Iterable[type] | None = None
439
- ) -> bool:
440
- """
441
- Judge whether it is iterable.
442
-
443
- Parameters
444
- ----------
445
- obj : Judge object.
446
- exclude_types : Non iterative types.
447
-
448
- Returns
449
- -------
450
- Judgment result.
451
- """
452
-
453
- # Judge.
454
- if (
455
- hasattr(obj, '__iter__')
456
- and not (
457
- exclude_types is not None
458
- and type(obj) in exclude_types
459
- )
460
- ):
461
- return True
462
-
463
- return False
464
-
465
-
466
- def is_table(
467
- obj: Any,
468
- check_fields: bool = True
469
- ) -> bool:
470
- """
471
- Judge whether it is `list[dict]` table format and keys and keys sort of the dict are the same.
472
-
473
- Parameters
474
- ----------
475
- obj : Judge object.
476
- check_fields : Do you want to check the keys and keys sort of the dict are the same.
477
-
478
- Returns
479
- -------
480
- Judgment result.
481
- """
482
-
483
- # Judge.
484
- if type(obj) != list:
485
- return False
486
- for element in obj:
487
- if type(element) != dict:
488
- return False
489
-
490
- ## Check fields of table.
491
- if check_fields:
492
- keys_strs = [
493
- ':'.join([str(key) for key in element.keys()])
494
- for element in obj
495
- ]
496
- keys_strs_only = set(keys_strs)
497
- if len(keys_strs_only) != 1:
498
- return False
499
-
500
- return True
501
-
502
-
503
- def is_number_str(
504
- string: str
505
- ) -> bool:
506
- """
507
- Judge whether it is number string.
508
-
509
- Parameters
510
- ----------
511
- string : String.
512
-
513
- Returns
514
- -------
515
- Judgment result.
516
- """
517
-
518
- # Judge.
519
- try:
520
- float(string)
521
- except (ValueError, TypeError):
522
- return False
523
-
524
- return True
525
-
526
-
527
- def get_first_notnull(
528
- *values: Any,
529
- default: Any | Literal['exception'] | None = None,
530
- nulls: tuple = (None,)) -> Any:
531
- """
532
- Get the first value that is not null.
533
-
534
- Parameters
535
- ----------
536
- values : Check values.
537
- default : When all are null, then return this is value, or throw exception.
538
- - `Any`: Return this is value.
539
- - `Literal['exception']`: Throw `exception`.
540
- nulls : Range of null values.
541
-
542
- Returns
543
- -------
544
- Return first not null value, when all are `None`, then return default value.
545
- """
546
-
547
- # Get value.
548
- for value in values:
549
- if value not in nulls:
550
- return value
551
-
552
- # Throw exception.
553
- if default == 'exception':
554
- vars_name = get_name(values)
555
- if vars_name is not None:
556
- vars_name_de_dup = list(set(vars_name))
557
- vars_name_de_dup.sort(key=vars_name.index)
558
- vars_name_str = ' ' + ' and '.join([f'"{var_name}"' for var_name in vars_name_de_dup])
559
- else:
560
- vars_name_str = ''
561
- raise ValueError(f'at least one of parameters{vars_name_str} is not None')
562
-
563
- return default
564
-
565
-
566
- @overload
567
- def get_name(obj: tuple, frame: int = 2) -> tuple[str, ...] | None: ...
568
-
569
- @overload
570
- def get_name(obj: Any, frame: int = 2) -> str | None: ...
571
-
572
- def get_name(obj: Any, frame: int = 2) -> str | tuple[str, ...] | None:
573
- """
574
- Get name of object or variable.
575
-
576
- Parameters
577
- ----------
578
- obj : Object.
579
- - `tuple`: Variable length position parameter of previous layer.
580
- - `Any`: Parameter of any layer.
581
- frame : Number of code to upper level.
582
-
583
- Returns
584
- -------
585
- Name or None.
586
- """
587
-
588
- # Get name using built in method.
589
- if hasattr(obj, '__name__'):
590
- name = obj.__name__
591
- return name
592
-
593
- # Get name using module method.
594
- name = 'obj'
595
- for frame_ in range(1, frame + 1):
596
- if type(name) != str:
597
- return
598
- try:
599
- name = argname(name, frame=frame_)
600
- except VarnameRetrievingError:
601
- return
602
- if type(name) == tuple:
603
- for element in name:
604
- if type(element) != str:
605
- return
606
-
607
- return name
608
-
609
-
610
- def get_stack_text(format_: Literal['plain', 'full'] = 'plain', limit: int = 2) -> str:
611
- """
612
- Get code stack text.
613
-
614
- Parameters
615
- ----------
616
- format_ : Stack text format.
617
- - `Literal['plain']`: Floor stack position.
618
- - `Literal['full']`: Full stack information.
619
- limit : Stack limit level.
620
-
621
- Returns
622
- -------
623
- Code stack text.
624
- """
625
-
626
- # Get.
627
- match format_:
628
-
629
- ## Plain.
630
- case 'plain':
631
- limit += 1
632
- stacks = format_stack(limit=limit)
633
-
634
- ### Check.
635
- if len(stacks) != limit:
636
- throw(value=limit)
637
-
638
- ### Convert.
639
- text = stacks[0]
640
- index_end = text.find(', in ')
641
- text = text[2:index_end]
642
-
643
- ## Full.
644
- case 'full':
645
- stacks = format_stack()
646
- index_limit = len(stacks) - limit
647
- stacks = stacks[:index_limit]
648
-
649
- ### Check.
650
- if len(stacks) == 0:
651
- throw(value=limit)
652
-
653
- ### Convert.
654
- stacks = [
655
- stack[2:].replace('\n ', '\n', 1)
656
- for stack in stacks
657
- ]
658
- text = ''.join(stacks)
659
- text = text[:-1]
660
-
661
- ## Throw exception.
662
- case _:
663
- throw(ValueError, format_)
664
-
665
- return text
666
-
667
-
668
- @overload
669
- def get_stack_param(format_: Literal['floor'] = 'floor', limit: int = 2) -> dict: ...
670
-
671
- @overload
672
- def get_stack_param(format_: Literal['full'] = 'floor', limit: int = 2) -> list[dict]: ...
673
-
674
- def get_stack_param(format_: Literal['floor', 'full'] = 'floor', limit: int = 2) -> dict | list[dict]:
675
- """
676
- Get code stack parameters.
677
-
678
- Parameters
679
- ----------
680
- format_ : Stack parameters format.
681
- - `Literal['floor']`: Floor stack parameters.
682
- - `Literal['full']`: Full stack parameters.
683
- limit : Stack limit level.
684
-
685
- Returns
686
- -------
687
- Code stack parameters.
688
- """
689
-
690
- # Get.
691
- stacks = extract_stack()
692
- index_limit = len(stacks) - limit
693
- stacks = stacks[:index_limit]
694
-
695
- # Check.
696
- if len(stacks) == 0:
697
- throw(value=limit)
698
-
699
- # Convert.
700
- match format_:
701
-
702
- ## Floor.
703
- case 'floor':
704
- stack = stacks[-1]
705
- params = {
706
- 'filename': stack.filename,
707
- 'lineno': stack.lineno,
708
- 'name': stack.name,
709
- 'line': stack.line
710
- }
711
-
712
- ## Full.
713
- case 'full':
714
- params = [
715
- {
716
- 'filename': stack.filename,
717
- 'lineno': stack.lineno,
718
- 'name': stack.name,
719
- 'line': stack.line
720
- }
721
- for stack in stacks
722
- ]
723
-
724
- return params
725
-
726
-
727
- def get_arg_info(func: Callable) -> list[
728
- dict[
729
- Literal['name', 'type', 'annotation', 'default'],
730
- str | None
731
- ]
732
- ]:
733
- """
734
- Get function arguments information.
735
-
736
- Parameters
737
- ----------
738
- func : Function.
739
-
740
- Returns
741
- -------
742
- Arguments information.
743
- - `Value of key 'name'`: Argument name.
744
- - `Value of key 'type'`: Argument bind type.
745
- `Literal['position_or_keyword']`: Is positional argument or keyword argument.
746
- `Literal['var_position']`: Is variable length positional argument.
747
- `Literal['var_keyword']`: Is variable length keyword argument.
748
- `Literal['only_position']`: Is positional only argument.
749
- `Literal['only_keyword']`: Is keyword only argument.
750
- - `Value of key 'annotation'`: Argument annotation.
751
- - `Value of key 'default'`: Argument default value.
752
- """
753
-
754
- # Get signature.
755
- signature = inspect_signature(func)
756
-
757
- # Get information.
758
- info = [
759
- {
760
- 'name': name,
761
- 'type': (
762
- 'position_or_keyword'
763
- if parameter.kind == _ParameterKind.POSITIONAL_OR_KEYWORD
764
- else 'var_position'
765
- if parameter.kind == _ParameterKind.VAR_POSITIONAL
766
- else 'var_keyword'
767
- if parameter.kind == _ParameterKind.VAR_KEYWORD
768
- else 'only_position'
769
- if parameter.kind == _ParameterKind.POSITIONAL_ONLY
770
- else 'only_keyword'
771
- if parameter.kind == _ParameterKind.KEYWORD_ONLY
772
- else None
773
- ),
774
- 'annotation': parameter.annotation,
775
- 'default': parameter.default
776
- }
777
- for name, parameter in signature.parameters.items()
778
- ]
779
-
780
- # Replace empty.
781
- for row in info:
782
- for key, value in row.items():
783
- if value == _empty:
784
- row[key] = None
785
-
786
- return info
787
-
788
-
789
322
  def get_computer_info() -> ComputerInfo:
790
323
  """
791
324
  Get computer information.
@@ -1083,7 +616,7 @@ def kill_process(
1083
616
  # Search.
1084
617
  processes = search_process(id_, name, port)
1085
618
 
1086
- # Start.
619
+ # Kill.
1087
620
  for process in processes:
1088
621
  with process.oneshot():
1089
622
 
@@ -1096,13 +629,13 @@ def kill_process(
1096
629
  return processes
1097
630
 
1098
631
 
1099
- def stop_process(
632
+ def pause_process(
1100
633
  id_: int | Sequence[int] | None = None,
1101
634
  name: str | Sequence[str] | None = None,
1102
635
  port: str | int | Sequence[str | int] | None = None,
1103
636
  ) -> list[Process]:
1104
637
  """
1105
- Search and stop process by ID or name or port.
638
+ Search and pause process by ID or name or port.
1106
639
 
1107
640
  Parameters
1108
641
  ----------
@@ -1121,7 +654,7 @@ def stop_process(
1121
654
  # Search.
1122
655
  processes = search_process(id_, name, port)
1123
656
 
1124
- # Start.
657
+ # Pause.
1125
658
  for process in processes:
1126
659
  with process.oneshot():
1127
660
 
@@ -1134,13 +667,13 @@ def stop_process(
1134
667
  return processes
1135
668
 
1136
669
 
1137
- def start_process(
670
+ def resume_process(
1138
671
  id_: int | Sequence[int] | None = None,
1139
672
  name: str | Sequence[str] | None = None,
1140
673
  port: str | int | Sequence[str | int] | None = None,
1141
674
  ) -> list[Process]:
1142
675
  """
1143
- Search and start process by ID or name or port.
676
+ Search and resume process by ID or name or port.
1144
677
 
1145
678
  Parameters
1146
679
  ----------
@@ -1156,7 +689,7 @@ def start_process(
1156
689
  # Search.
1157
690
  processes = search_process(id_, name, port)
1158
691
 
1159
- # Start.
692
+ # Resume.
1160
693
  for process in processes:
1161
694
  with process.oneshot():
1162
695
  process.resume()
@@ -1319,17 +852,17 @@ def popup_message(
1319
852
 
1320
853
  @overload
1321
854
  def popup_ask(
1322
- style: Literal['yes_no_cancel'] = 'yes_no',
855
+ style: Literal['yes_no', 'ok_cancel', 'retry_cancel'] = 'yes_no',
1323
856
  message: str | None = None,
1324
857
  title: str | None = None
1325
- ) -> bool | None: ...
858
+ ) -> bool: ...
1326
859
 
1327
860
  @overload
1328
861
  def popup_ask(
1329
- style: Literal['yes_no', 'ok_cancel', 'retry_cancel'] = 'yes_no',
862
+ style: Literal['yes_no_cancel'],
1330
863
  message: str | None = None,
1331
864
  title: str | None = None
1332
- ) -> bool: ...
865
+ ) -> bool | None: ...
1333
866
 
1334
867
  def popup_ask(
1335
868
  style: Literal['yes_no', 'ok_cancel', 'retry_cancel', 'yes_no_cancel'] = 'yes_no',
@@ -1387,7 +920,7 @@ def popup_select(
1387
920
 
1388
921
  @overload
1389
922
  def popup_select(
1390
- style: Literal['files'] = 'file',
923
+ style: Literal['files'],
1391
924
  title : str | None = None,
1392
925
  init_folder : str | None = None,
1393
926
  init_file : str | None = None,
@@ -1396,7 +929,7 @@ def popup_select(
1396
929
 
1397
930
  @overload
1398
931
  def popup_select(
1399
- style: Literal['folder'] = 'file',
932
+ style: Literal['folder'],
1400
933
  title : str | None = None,
1401
934
  init_folder : str | None = None
1402
935
  ) -> str | None: ...