kaqing 2.0.184__py3-none-any.whl → 2.0.227__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.

Potentially problematic release.


This version of kaqing might be problematic. Click here for more details.

Files changed (205) hide show
  1. adam/app_session.py +1 -1
  2. adam/batch.py +15 -15
  3. adam/checks/compactionstats.py +2 -1
  4. adam/checks/cpu.py +2 -1
  5. adam/checks/disk.py +6 -5
  6. adam/checks/gossip.py +2 -1
  7. adam/checks/memory.py +2 -1
  8. adam/checks/status.py +2 -1
  9. adam/commands/app/app.py +4 -4
  10. adam/commands/app/app_ping.py +2 -2
  11. adam/commands/{login.py → app/login.py} +2 -2
  12. adam/commands/app/show_app_actions.py +3 -3
  13. adam/commands/app/show_app_id.py +2 -2
  14. adam/commands/app/show_app_queues.py +2 -2
  15. adam/commands/{show → app}/show_login.py +3 -3
  16. adam/commands/app/utils_app.py +9 -1
  17. adam/commands/audit/audit.py +8 -24
  18. adam/commands/audit/audit_repair_tables.py +3 -3
  19. adam/commands/audit/audit_run.py +3 -3
  20. adam/commands/audit/completions_l.py +15 -0
  21. adam/commands/audit/show_last10.py +2 -3
  22. adam/commands/audit/show_slow10.py +2 -2
  23. adam/commands/audit/show_top10.py +2 -2
  24. adam/commands/bash/bash.py +3 -3
  25. adam/commands/bash/utils_bash.py +1 -1
  26. adam/commands/cassandra/download_cassandra_log.py +45 -0
  27. adam/commands/cassandra/restart_cluster.py +47 -0
  28. adam/commands/cassandra/restart_node.py +51 -0
  29. adam/commands/cassandra/restart_nodes.py +47 -0
  30. adam/commands/{rollout.py → cassandra/rollout.py} +3 -3
  31. adam/commands/{show → cassandra}/show_cassandra_repairs.py +7 -5
  32. adam/commands/{show → cassandra}/show_cassandra_status.py +24 -17
  33. adam/commands/{show → cassandra}/show_cassandra_version.py +2 -2
  34. adam/commands/cassandra/show_processes.py +50 -0
  35. adam/commands/cassandra/show_storage.py +44 -0
  36. adam/commands/{watch.py → cassandra/watch.py} +2 -2
  37. adam/commands/cli/__init__.py +0 -0
  38. adam/commands/{cli_commands.py → cli/cli_commands.py} +6 -1
  39. adam/commands/{clipboard_copy.py → cli/clipboard_copy.py} +4 -4
  40. adam/commands/{show/show_commands.py → cli/show_cli_commands.py} +5 -5
  41. adam/commands/code.py +2 -2
  42. adam/commands/command.py +54 -14
  43. adam/commands/commands_utils.py +14 -6
  44. adam/commands/config/__init__.py +0 -0
  45. adam/commands/{param_get.py → config/param_get.py} +2 -2
  46. adam/commands/{param_set.py → config/param_set.py} +2 -2
  47. adam/commands/{show → config}/show_params.py +3 -3
  48. adam/commands/{alter_tables.py → cql/alter_tables.py} +3 -3
  49. adam/commands/cql/completions_c.py +29 -0
  50. adam/commands/cql/cqlsh.py +4 -8
  51. adam/commands/cql/utils_cql.py +36 -17
  52. adam/commands/debug/__init__.py +0 -0
  53. adam/commands/debug/debug.py +22 -0
  54. adam/commands/debug/debug_completes.py +35 -0
  55. adam/commands/debug/debug_timings.py +35 -0
  56. adam/commands/debug/show_offloaded_completes.py +45 -0
  57. adam/commands/deploy/code_start.py +2 -2
  58. adam/commands/deploy/code_stop.py +2 -2
  59. adam/commands/deploy/deploy_frontend.py +2 -2
  60. adam/commands/deploy/deploy_pg_agent.py +2 -2
  61. adam/commands/deploy/deploy_pod.py +2 -2
  62. adam/commands/deploy/undeploy_frontend.py +2 -2
  63. adam/commands/deploy/undeploy_pg_agent.py +2 -2
  64. adam/commands/deploy/undeploy_pod.py +2 -2
  65. adam/commands/devices/device.py +37 -11
  66. adam/commands/devices/device_app.py +7 -7
  67. adam/commands/devices/device_auit_log.py +2 -2
  68. adam/commands/devices/device_cass.py +6 -6
  69. adam/commands/devices/device_export.py +7 -4
  70. adam/commands/devices/device_postgres.py +19 -9
  71. adam/commands/devices/devices.py +1 -1
  72. adam/commands/diag/__init__.py +0 -0
  73. adam/commands/{check.py → diag/check.py} +3 -3
  74. adam/commands/diag/generate_report.py +52 -0
  75. adam/commands/{issues.py → diag/issues.py} +3 -2
  76. adam/commands/exit.py +2 -2
  77. adam/commands/export/clean_up_all_export_sessions.py +2 -2
  78. adam/commands/export/clean_up_export_sessions.py +2 -2
  79. adam/commands/export/completions_x.py +11 -0
  80. adam/commands/export/download_export_session.py +5 -5
  81. adam/commands/export/drop_export_database.py +2 -2
  82. adam/commands/export/drop_export_databases.py +2 -2
  83. adam/commands/export/export.py +3 -19
  84. adam/commands/export/export_databases.py +20 -11
  85. adam/commands/export/export_select.py +9 -34
  86. adam/commands/export/export_sessions.py +13 -11
  87. adam/commands/export/export_use.py +6 -6
  88. adam/commands/export/export_x_select.py +48 -0
  89. adam/commands/export/exporter.py +140 -53
  90. adam/commands/export/import_files.py +3 -7
  91. adam/commands/export/import_session.py +2 -6
  92. adam/commands/export/importer.py +12 -13
  93. adam/commands/export/importer_athena.py +15 -35
  94. adam/commands/export/importer_sqlite.py +19 -8
  95. adam/commands/export/show_column_counts.py +11 -12
  96. adam/commands/export/show_export_databases.py +4 -4
  97. adam/commands/export/show_export_session.py +5 -5
  98. adam/commands/export/show_export_sessions.py +4 -4
  99. adam/commands/export/utils_export.py +40 -25
  100. adam/commands/fs/__init__.py +0 -0
  101. adam/commands/{cat.py → fs/cat.py} +4 -4
  102. adam/commands/fs/cat_local.py +42 -0
  103. adam/commands/{cd.py → fs/cd.py} +4 -4
  104. adam/commands/{download_file.py → fs/download_file.py} +7 -7
  105. adam/commands/{find_files.py → fs/find_files.py} +7 -7
  106. adam/commands/{find_processes.py → fs/find_processes.py} +14 -22
  107. adam/commands/{head.py → fs/head.py} +5 -5
  108. adam/commands/fs/head_local.py +46 -0
  109. adam/commands/{ls.py → fs/ls.py} +4 -4
  110. adam/commands/fs/ls_local.py +40 -0
  111. adam/commands/{pwd.py → fs/pwd.py} +2 -2
  112. adam/commands/fs/rm.py +18 -0
  113. adam/commands/fs/rm_downloads.py +39 -0
  114. adam/commands/fs/rm_logs.py +44 -0
  115. adam/commands/fs/rm_logs_local.py +38 -0
  116. adam/commands/{shell.py → fs/shell.py} +2 -2
  117. adam/commands/{show → fs}/show_adam.py +3 -3
  118. adam/commands/{show → fs}/show_host.py +2 -2
  119. adam/commands/fs/show_last_results.py +39 -0
  120. adam/commands/fs/tail.py +36 -0
  121. adam/commands/fs/tail_local.py +46 -0
  122. adam/commands/fs/utils_fs.py +192 -0
  123. adam/commands/help.py +2 -2
  124. adam/commands/intermediate_command.py +3 -0
  125. adam/commands/kubectl.py +2 -2
  126. adam/commands/medusa/medusa_backup.py +2 -2
  127. adam/commands/medusa/medusa_restore.py +4 -18
  128. adam/commands/medusa/medusa_show_backupjobs.py +2 -2
  129. adam/commands/medusa/medusa_show_restorejobs.py +2 -2
  130. adam/commands/medusa/utils_medusa.py +15 -0
  131. adam/commands/nodetool/__init__.py +0 -0
  132. adam/commands/nodetool/nodetool.py +87 -0
  133. adam/commands/nodetool/utils_nodetool.py +44 -0
  134. adam/commands/postgres/completions_p.py +22 -0
  135. adam/commands/postgres/postgres.py +10 -20
  136. adam/commands/postgres/postgres_databases.py +3 -3
  137. adam/commands/postgres/postgres_ls.py +3 -3
  138. adam/commands/postgres/postgres_preview.py +2 -2
  139. adam/commands/postgres/utils_postgres.py +12 -2
  140. adam/commands/preview_table.py +3 -4
  141. adam/commands/reaper/reaper_forward.py +2 -2
  142. adam/commands/reaper/reaper_forward_stop.py +2 -2
  143. adam/commands/reaper/reaper_restart.py +2 -2
  144. adam/commands/reaper/reaper_run_abort.py +2 -2
  145. adam/commands/reaper/reaper_runs.py +14 -12
  146. adam/commands/reaper/reaper_runs_abort.py +2 -2
  147. adam/commands/reaper/reaper_schedule_activate.py +8 -4
  148. adam/commands/reaper/reaper_schedule_start.py +3 -4
  149. adam/commands/reaper/reaper_schedule_stop.py +3 -4
  150. adam/commands/reaper/reaper_schedules.py +2 -2
  151. adam/commands/reaper/reaper_status.py +2 -2
  152. adam/commands/reaper/utils_reaper.py +41 -6
  153. adam/commands/repair/repair_log.py +2 -2
  154. adam/commands/repair/repair_run.py +2 -2
  155. adam/commands/repair/repair_scan.py +2 -4
  156. adam/commands/repair/repair_stop.py +2 -3
  157. adam/commands/{show/show.py → show.py} +12 -11
  158. adam/config.py +4 -5
  159. adam/embedded_params.py +1 -1
  160. adam/repl.py +24 -10
  161. adam/repl_commands.py +68 -45
  162. adam/repl_session.py +16 -1
  163. adam/repl_state.py +16 -1
  164. adam/sql/async_executor.py +62 -0
  165. adam/sql/lark_completer.py +286 -0
  166. adam/sql/lark_parser.py +604 -0
  167. adam/sql/qingl.lark +1075 -0
  168. adam/sso/cred_cache.py +2 -5
  169. adam/utils.py +259 -82
  170. adam/utils_async_job.py +73 -0
  171. adam/utils_k8s/app_clusters.py +11 -4
  172. adam/utils_k8s/app_pods.py +10 -5
  173. adam/utils_k8s/cassandra_clusters.py +19 -7
  174. adam/utils_k8s/cassandra_nodes.py +16 -6
  175. adam/utils_k8s/k8s.py +9 -0
  176. adam/utils_k8s/kube_context.py +1 -4
  177. adam/{pod_exec_result.py → utils_k8s/pod_exec_result.py} +8 -2
  178. adam/utils_k8s/pods.py +189 -29
  179. adam/utils_k8s/statefulsets.py +5 -2
  180. adam/utils_local.py +78 -2
  181. adam/utils_repl/appendable_completer.py +6 -0
  182. adam/utils_repl/repl_completer.py +51 -4
  183. adam/utils_sqlite.py +3 -8
  184. adam/version.py +1 -1
  185. {kaqing-2.0.184.dist-info → kaqing-2.0.227.dist-info}/METADATA +1 -1
  186. kaqing-2.0.227.dist-info/RECORD +280 -0
  187. kaqing-2.0.227.dist-info/top_level.txt +2 -0
  188. teddy/__init__.py +0 -0
  189. teddy/lark_parser.py +436 -0
  190. teddy/lark_parser2.py +618 -0
  191. adam/commands/cql/cql_completions.py +0 -32
  192. adam/commands/export/export_select_x.py +0 -54
  193. adam/commands/logs.py +0 -37
  194. adam/commands/nodetool.py +0 -69
  195. adam/commands/postgres/psql_completions.py +0 -11
  196. adam/commands/report.py +0 -61
  197. adam/commands/restart.py +0 -60
  198. adam/commands/show/show_processes.py +0 -49
  199. adam/commands/show/show_storage.py +0 -42
  200. kaqing-2.0.184.dist-info/RECORD +0 -244
  201. kaqing-2.0.184.dist-info/top_level.txt +0 -1
  202. /adam/commands/{show → cassandra}/__init__.py +0 -0
  203. /adam/commands/{nodetool_commands.py → nodetool/nodetool_commands.py} +0 -0
  204. {kaqing-2.0.184.dist-info → kaqing-2.0.227.dist-info}/WHEEL +0 -0
  205. {kaqing-2.0.184.dist-info → kaqing-2.0.227.dist-info}/entry_points.txt +0 -0
adam/repl_commands.py CHANGED
@@ -1,13 +1,33 @@
1
- from adam.commands.alter_tables import AlterTables
2
1
  from adam.commands.app.app import App
3
2
  from adam.commands.app.app_ping import AppPing
4
3
  from adam.commands.app.show_app_actions import ShowAppActions
5
4
  from adam.commands.app.show_app_id import ShowAppId
6
5
  from adam.commands.app.show_app_queues import ShowAppQueues
7
6
  from adam.commands.audit.audit import Audit
8
- from adam.commands.cat import Cat
7
+ from adam.commands.cassandra.restart_cluster import RestartCluster
8
+ from adam.commands.cassandra.restart_node import RestartNode
9
+ from adam.commands.cassandra.restart_nodes import RestartNodes
10
+ from adam.commands.cassandra.rollout import RollOut
11
+ from adam.commands.cassandra.show_cassandra_repairs import ShowCassandraRepairs
12
+ from adam.commands.cassandra.show_cassandra_status import ShowCassandraStatus
13
+ from adam.commands.cassandra.show_cassandra_version import ShowCassandraVersion
14
+ from adam.commands.cassandra.show_processes import ShowProcesses
15
+ from adam.commands.cassandra.show_storage import ShowStorage
16
+ from adam.commands.cassandra.watch import Watch
17
+ from adam.commands.cli.clipboard_copy import ClipboardCopy
18
+ from adam.commands.config.param_get import GetParam
19
+ from adam.commands.config.param_set import SetParam
20
+ from adam.commands.debug.show_offloaded_completes import ShowOffloadedCompletes
21
+ from adam.commands.diag.check import Check
22
+ from adam.commands.diag.generate_report import GenerateReport
23
+ from adam.commands.diag.issues import Issues
24
+ from adam.commands.fs.cat import Cat
9
25
  from adam.commands.code import Code
10
- from adam.commands.download_file import DownloadFile
26
+ from adam.commands.cql.alter_tables import AlterTables
27
+ from adam.commands.debug.debug import Debug
28
+ from adam.commands.cassandra.download_cassandra_log import DownloadCassandraLog
29
+ from adam.commands.fs.cat_local import CatLocal
30
+ from adam.commands.fs.download_file import DownloadFile
11
31
  from adam.commands.deploy.code_start import CodeStart
12
32
  from adam.commands.deploy.code_stop import CodeStop
13
33
  from adam.commands.deploy.deploy import Deploy
@@ -31,58 +51,51 @@ from adam.commands.export.import_session import ImportSession
31
51
  from adam.commands.export.clean_up_export_sessions import CleanUpExportSessions
32
52
  from adam.commands.export.clean_up_all_export_sessions import CleanUpAllExportSessions
33
53
  from adam.commands.export.drop_export_databases import DropExportDatabases
34
- from adam.commands.export.export_select import ExportSelect
54
+ from adam.commands.export.export_x_select import ExportXSelect
35
55
  from adam.commands.export.export_use import ExportUse
36
- from adam.commands.export.export_select_x import ExportSelectX
56
+ from adam.commands.export.export_select import ExportSelect
37
57
  from adam.commands.export.show_column_counts import ShowColumnCounts
38
58
  from adam.commands.export.show_export_databases import ShowExportDatabases
39
59
  from adam.commands.export.show_export_session import ShowExportSession
40
60
  from adam.commands.export.show_export_sessions import ShowExportSessions
41
- from adam.commands.find_files import FindLocalFiles
42
- from adam.commands.find_processes import FindProcesses
43
- from adam.commands.head import Head
61
+ from adam.commands.fs.find_files import FindLocalFiles
62
+ from adam.commands.fs.find_processes import FindProcesses
63
+ from adam.commands.fs.head import Head
64
+ from adam.commands.fs.head_local import HeadLocal
65
+ from adam.commands.fs.ls_local import LsLocal
66
+ from adam.commands.fs.rm import RmLocal
67
+ from adam.commands.fs.rm_logs import RmLogs
68
+ from adam.commands.fs.show_last_results import ShowLastResults
69
+ from adam.commands.fs.tail import Tail
70
+ from adam.commands.fs.tail_local import TailLocal
44
71
  from adam.commands.kubectl import Kubectl
45
- from adam.commands.shell import Shell
46
- from adam.commands.clipboard_copy import ClipboardCopy
72
+ from adam.commands.fs.shell import Shell
47
73
  from adam.commands.bash.bash import Bash
48
- from adam.commands.cd import Cd
49
- from adam.commands.check import Check
74
+ from adam.commands.fs.cd import Cd
50
75
  from adam.commands.command import Command
51
76
  from adam.commands.cql.cqlsh import Cqlsh
52
77
  from adam.commands.exit import Exit
53
78
  from adam.commands.medusa.medusa import Medusa
54
- from adam.commands.param_get import GetParam
55
- from adam.commands.issues import Issues
56
- from adam.commands.ls import Ls
57
- from adam.commands.nodetool import NodeTool
79
+ from adam.commands.fs.ls import Ls
80
+ from adam.commands.nodetool.nodetool import NodeTool
58
81
  from adam.commands.postgres.postgres import Postgres, PostgresPg
59
82
  from adam.commands.preview_table import PreviewTable
60
- from adam.commands.pwd import Pwd
83
+ from adam.commands.fs.pwd import Pwd
61
84
  from adam.commands.reaper.reaper import Reaper
62
85
  from adam.commands.repair.repair import Repair
63
- from adam.commands.report import Report
64
- from adam.commands.restart import Restart
65
- from adam.commands.rollout import RollOut
66
- from adam.commands.param_set import SetParam
67
- from adam.commands.show.show import Show
68
- from adam.commands.show.show_cassandra_status import ShowCassandraStatus
69
- from adam.commands.show.show_cassandra_version import ShowCassandraVersion
70
- from adam.commands.show.show_commands import ShowKubectlCommands
71
- from adam.commands.show.show_host import ShowHost
72
- from adam.commands.show.show_login import ShowLogin
73
- from adam.commands.show.show_params import ShowParams
74
- from adam.commands.show.show_processes import ShowProcesses
75
- from adam.commands.show.show_cassandra_repairs import ShowCassandraRepairs
76
- from adam.commands.show.show_storage import ShowStorage
77
- from adam.commands.show.show_adam import ShowAdam
78
- from adam.commands.watch import Watch
86
+ from adam.commands.cli.show_cli_commands import ShowKubectlCommands
87
+ from adam.commands.fs.show_host import ShowHost
88
+ from adam.commands.app.show_login import ShowLogin
89
+ from adam.commands.config.show_params import ShowParams
90
+ from adam.commands.fs.show_adam import ShowAdam
91
+ from adam.commands.show import Show
79
92
 
80
93
  class ReplCommands:
81
94
  def repl_cmd_list() -> list[Command]:
82
95
  cmds: list[Command] = ReplCommands.navigation() + ReplCommands.cassandra_ops() + ReplCommands.postgres_ops() + \
83
96
  ReplCommands.app_ops() + ReplCommands.audit_ops() + ReplCommands.export_ops() + ReplCommands.tools() + ReplCommands.exit()
84
97
 
85
- intermediate_cmds: list[Command] = [App(), Audit(), Reaper(), Repair(), Deploy(), Show(), Undeploy()]
98
+ intermediate_cmds: list[Command] = [App(), Audit(), Reaper(), Repair(), Debug(), Deploy(), Show(), Undeploy()]
86
99
  ic = [c.command() for c in intermediate_cmds]
87
100
  # 1. dedup commands
88
101
  deduped = []
@@ -99,18 +112,28 @@ class ReplCommands:
99
112
  return deduped
100
113
 
101
114
  def navigation() -> list[Command]:
102
- return [Ls(), PreviewTable(), DeviceApp(), DevicePostgres(), DeviceCass(), DeviceAuditLog(), DeviceExport(),
103
- Cd(), Cat(), Head(), DownloadFile(), FindLocalFiles(), FindProcesses(), Pwd(), ClipboardCopy(),
104
- GetParam(), SetParam(), ShowParams(), ShowKubectlCommands(), ShowLogin(), ShowAdam(), ShowHost()]
115
+ return [Cd(), Cat(), CatLocal(), ClipboardCopy(),
116
+ DeviceApp(), DevicePostgres(), DeviceCass(), DeviceAuditLog(), DeviceExport(),
117
+ DownloadFile(), FindLocalFiles(), FindProcesses(), GetParam(),
118
+ Head(), HeadLocal(), Ls(), LsLocal(), PreviewTable(), Pwd(), RmLogs(),
119
+ SetParam(), ShowAdam(), ShowHost(), ShowKubectlCommands(), ShowLastResults(),
120
+ ShowLogin(), ShowOffloadedCompletes(), ShowParams(),
121
+ Tail(), TailLocal()] + \
122
+ RmLocal().cmd_list()
105
123
 
106
124
  def cassandra_ops() -> list[Command]:
107
- return [Cqlsh(), ShowCassandraStatus(), ShowCassandraVersion(), ShowCassandraRepairs(), ShowStorage(), ShowProcesses(),
108
- Check(), Issues(), NodeTool(), Report(), AlterTables(), Bash(),
109
- ExportTables(), ExportSelect(), ExportUse(), ShowExportDatabases(), ShowColumnCounts(),
110
- DropExportDatabase(), DropExportDatabases(),
111
- ShowExportSessions(), ShowExportSession(), DownloadExportSession(),
112
- CleanUpExportSessions(), CleanUpAllExportSessions(), ImportSession(), ImportCSVFiles()] + \
113
- Medusa().cmd_list() + [Restart(), RollOut(), Watch()] + Reaper().cmd_list() + Repair().cmd_list()
125
+ return [AlterTables(), Bash(), Check(), CleanUpExportSessions(), CleanUpAllExportSessions(), Cqlsh(),
126
+ DownloadCassandraLog(), DropExportDatabase(), DropExportDatabases(), DownloadExportSession(),
127
+ ExportTables(), ExportXSelect(), ExportUse(),
128
+ GenerateReport(), ImportSession(), ImportCSVFiles(), Issues(), NodeTool(),
129
+ RestartNodes(), RestartNode(), RestartCluster(), RollOut(),
130
+ ShowCassandraStatus(), ShowCassandraVersion(), ShowCassandraRepairs(), ShowColumnCounts(),
131
+ ShowStorage(), ShowExportDatabases(), ShowExportSessions(), ShowExportSession(), ShowProcesses(),
132
+ Watch()] + \
133
+ Debug().cmd_list() + \
134
+ Medusa().cmd_list() + \
135
+ Reaper().cmd_list() + \
136
+ Repair().cmd_list()
114
137
 
115
138
  def postgres_ops() -> list[Command]:
116
139
  return [Postgres(), DeployPgAgent(), UndeployPgAgent(), PostgresPg()]
@@ -122,7 +145,7 @@ class ReplCommands:
122
145
  return [Audit()] + Audit().cmd_list()
123
146
 
124
147
  def export_ops() -> list[Command]:
125
- return [ExportSelectX(), DropExportDatabase(), DropExportDatabases(), ShowColumnCounts()]
148
+ return [ExportSelect(), DropExportDatabase(), DropExportDatabases(), ShowColumnCounts()]
126
149
 
127
150
  def tools() -> list[Command]:
128
151
  return [Shell(), CodeStart(), CodeStop(), DeployFrontend(), UndeployFrontend(), DeployPod(), UndeployPod(), Kubectl(), Code()]
adam/repl_session.py CHANGED
@@ -1,6 +1,10 @@
1
+ from typing import Union
1
2
  from prompt_toolkit import PromptSession
2
3
  from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
3
4
 
5
+ from adam.config import Config
6
+ from adam.utils import ConfigHolder, LogFile
7
+
4
8
  class ReplSession:
5
9
  # the singleton pattern
6
10
  def __new__(cls, *args, **kwargs):
@@ -10,4 +14,15 @@ class ReplSession:
10
14
 
11
15
  def __init__(self):
12
16
  if not hasattr(self, 'prompt_session'):
13
- self.prompt_session = PromptSession(auto_suggest=AutoSuggestFromHistory())
17
+ self.prompt_session = PromptSession(auto_suggest=AutoSuggestFromHistory())
18
+ ConfigHolder().append_command_history = self.append_history
19
+
20
+ def append_history(self, entry: Union[str, LogFile]):
21
+ if not entry:
22
+ return
23
+
24
+ if self.prompt_session and Config().get('repl.history.push-cat-remote-log-file', True):
25
+ if isinstance(entry, LogFile):
26
+ entry = entry.to_command()
27
+
28
+ self.prompt_session.history.append_string(entry)
adam/repl_state.py CHANGED
@@ -61,6 +61,7 @@ class ReplState:
61
61
  self.bash_session = bash_session
62
62
  self.remote_dir = remote_dir
63
63
  self.original_state: ReplState = None
64
+ self.pod_targetted = False
64
65
 
65
66
  self.export_session: str = None
66
67
 
@@ -392,9 +393,10 @@ class ReplState:
392
393
  self.pop()
393
394
  self.bash_session = None
394
395
 
395
- def push(self):
396
+ def push(self, pod_targetted=False):
396
397
  if not self.original_state:
397
398
  self.original_state = copy(self)
399
+ self.pod_targetted = pod_targetted
398
400
 
399
401
  def pop(self):
400
402
  if o := self.original_state:
@@ -409,6 +411,7 @@ class ReplState:
409
411
  self.namespace = o.namespace
410
412
 
411
413
  self.original_state = None
414
+ self.pod_targetted = False
412
415
 
413
416
  def pg_host_n_database(self):
414
417
  host = None
@@ -422,6 +425,18 @@ class ReplState:
422
425
 
423
426
  return host, database
424
427
 
428
+ def with_no_pod(self):
429
+ state1 = copy(self)
430
+ state1.pod = None
431
+
432
+ return state1
433
+
434
+ def with_pod(self, pod: str):
435
+ state1 = copy(self)
436
+ state1.pod = pod
437
+
438
+ return state1
439
+
425
440
  class DevicePodService:
426
441
  def __init__(self, handler: 'DeviceExecHandler'):
427
442
  self.handler = handler
@@ -0,0 +1,62 @@
1
+ import asyncio
2
+ from concurrent.futures import ThreadPoolExecutor
3
+ from copy import copy
4
+ import inspect
5
+ import threading
6
+ import time
7
+ import traceback
8
+
9
+ from adam.utils import log2, log_timing
10
+
11
+ class AsyncExecutor:
12
+ # some lib does not handle asyncio loop properly, as sync exec submit does not work, use another async loop
13
+
14
+ lock = threading.Lock()
15
+ in_queue = set()
16
+ processed: dict[str, float] = {}
17
+ first_processed_at: float = None
18
+ last_processed_at: float = None
19
+
20
+ loop: asyncio.AbstractEventLoop = None
21
+ async_exec: ThreadPoolExecutor = None
22
+
23
+ def preload(action: callable, log_key: str = None):
24
+ with AsyncExecutor.lock:
25
+ if not AsyncExecutor.loop:
26
+ AsyncExecutor.loop = asyncio.new_event_loop()
27
+ AsyncExecutor.async_exec = ThreadPoolExecutor(max_workers=6, thread_name_prefix='async')
28
+ AsyncExecutor.loop.set_default_executor(AsyncExecutor.async_exec)
29
+
30
+ async def a():
31
+ try:
32
+ t0 = time.time()
33
+
34
+ arg_needed = len(action.__code__.co_varnames)
35
+
36
+ if log_key:
37
+ with log_timing(log_key):
38
+ r = action(None) if arg_needed else action()
39
+ else:
40
+ r = action(None) if arg_needed else action()
41
+ if inspect.isawaitable(r):
42
+ await r
43
+
44
+ AsyncExecutor.in_queue.remove(log_key)
45
+ if log_key not in AsyncExecutor.processed:
46
+ AsyncExecutor.processed[log_key] = time.time() - t0
47
+ AsyncExecutor.last_processed_at = time.time()
48
+ except Exception as e:
49
+ log2('preloading error', e, inspect.getsourcelines(action)[0][0])
50
+ traceback.print_exc()
51
+
52
+ if log_key not in AsyncExecutor.in_queue:
53
+ AsyncExecutor.in_queue.add(log_key)
54
+ AsyncExecutor.async_exec.submit(lambda: AsyncExecutor.loop.run_until_complete(a()))
55
+
56
+ def entries_in_queue():
57
+ # no locking
58
+ return copy(AsyncExecutor.in_queue), copy(AsyncExecutor.processed), AsyncExecutor.first_processed_at, AsyncExecutor.last_processed_at
59
+
60
+ def reset():
61
+ AsyncExecutor.first_processed_at = time.time()
62
+ AsyncExecutor.processed.clear()
@@ -0,0 +1,286 @@
1
+ import functools
2
+ import os
3
+ from typing import Iterable
4
+ from prompt_toolkit.completion import CompleteEvent, Completer, Completion, NestedCompleter, WordCompleter
5
+ from prompt_toolkit.document import Document
6
+
7
+ from adam.config import Config
8
+ from adam.sql.async_executor import AsyncExecutor
9
+ from adam.sql.lark_parser import LarkParser
10
+ from adam.utils import debug, log_timing, offload
11
+ from adam.utils_repl.appendable_completer import AppendableCompleter
12
+ from adam.utils_repl.repl_completer import merge_completions
13
+
14
+ __all__ = [
15
+ "LarkCompleter",
16
+ ]
17
+
18
+ def default_columns(x: list[str]):
19
+ return 'id,x.,y.,z.'.split(',')
20
+
21
+ class LarkCompleter(Completer, AppendableCompleter):
22
+ SYSTEM = 'system'
23
+
24
+ def __init__(self,
25
+ dml: str = None,
26
+ expandables: dict = {},
27
+ variant: str = 'c',
28
+
29
+ name: str = None,
30
+ options_lambda: callable = None,
31
+ auto: str = 'lazy',
32
+ debug = False
33
+ ) -> None:
34
+ self.nested: NestedCompleter = None
35
+ self.options_lambda = options_lambda
36
+ if options_lambda and auto == 'lazy':
37
+ AsyncExecutor.preload(options_lambda, log_key=name)
38
+
39
+ self.variant = variant
40
+ self.parser = None
41
+ self.dml = dml
42
+ self.expandables = expandables
43
+
44
+ self.display_dict = {}
45
+ self.meta_dict = {}
46
+ self.WORD = None
47
+ self.sentence = False
48
+ self.match_middle = False
49
+ self.pattern = None
50
+
51
+ self.debug = debug
52
+
53
+ if variant:
54
+ self.parser = LarkCompleter.lark_parser(variant)
55
+ self.preload_lazy_auto_completes()
56
+
57
+ def __repr__(self):
58
+ return f"LarkCompleter.{self.variant}"
59
+
60
+ def preload_lazy_auto_completes(self):
61
+ for key, value in self.expandables.items():
62
+ if callable(value):
63
+ if self.auto_complete(key) == 'lazy':
64
+ AsyncExecutor.preload(value, log_key=key)
65
+
66
+ def from_lambda(name: str, options_lambda: callable, auto: str = 'lazy'):
67
+ return LarkCompleter(name=name, options_lambda=options_lambda, auto=auto, variant=None)
68
+
69
+ @functools.lru_cache()
70
+ def lark_parser(variant: str):
71
+ dir_path = os.path.dirname(os.path.realpath(__file__))
72
+ with open(dir_path + f"/qingl.lark") as f:
73
+ grammar: str = None
74
+ with log_timing(f'lark.{variant}.file-read'):
75
+ grammar = f.read()
76
+
77
+ common_contexts = {
78
+ 'cd_command.file_name': 'direct-dirs',
79
+ }
80
+
81
+ if variant in ['a', 'c0', 'p0', 'x0']:
82
+ grammar = grammar.replace('start: statement_sequence', f'start: qing_{variant}_statement')
83
+ contexts_by_path = {
84
+ } | common_contexts
85
+
86
+ debug(f'* GRAMMAR replaced to start: qing_{variant}_statement')
87
+
88
+ return LarkParser(grammar, contexts_by_path)
89
+ elif variant == 'system':
90
+ grammar = grammar.replace('start: statement_sequence', f'start: qing_{variant}_statement')
91
+ contexts_by_path = {
92
+ } | common_contexts
93
+
94
+ return LarkParser(grammar, contexts_by_path)
95
+
96
+ grammar = grammar.replace('qing_statement: qing_p_statement', f'qing_statement: qing_{variant}_statement')
97
+ debug(f'* GRAMMAR replaced to qing_statement: qing_{variant}_statement')
98
+
99
+ bash_contexts = {
100
+ 'bash_statement.host_name': 'hosts',
101
+ 'bash_statement.bash_command': 'bash-commands',
102
+ }
103
+
104
+ contexts_by_path = {
105
+ 'describe_keyspace.keyspace_name': 'keyspaces',
106
+ 'keyspace_ref.keyspace_path.namespace_ref.identifier_ref': 'tables',
107
+ 'preview_table_statement.path.identifier_ref': 'tables',
108
+
109
+ 'insert_statement.insert_select': 'column-names',
110
+ 'update_statement.set_clause.path.identifier_ref': 'column-names',
111
+ 'update_statement.where_clause.cond.expr.path.identifier_ref': 'column-names',
112
+ 'delete_statement.where_clause.cond.expr.path.identifier_ref': 'column-names',
113
+
114
+ 'select_clause.projection.result_expr.expr.path.identifier_ref': 'columns',
115
+ 'select_from.where_clause.cond.expr.path.identifier_ref': 'columns',
116
+ 'select_from.where_clause.cond.expr.logical_term.and_expr.cond.expr.path.identifier_ref': 'columns',
117
+ 'select_from.group_by_clause.group_term.expr.path.identifier_ref': 'columns',
118
+ 'select_statement.order_by_clause.ordering_term.expr.path.identifier_ref': 'columns',
119
+ 'select_from.from_clause.from_terms.join_clause.ansi_join_clause.ansi_join_predicate.expr.path.identifier_ref': 'columns',
120
+ 'select_from.from_clause.from_terms.join_clause.ansi_join_clause.ansi_join_predicate.expr.comparison_term.relational_expr.expr.path.identifier_ref': 'columns',
121
+
122
+ 'select_from.from_clause.from_terms.from_generic.alias.identifier_ref': 'column-aliases',
123
+
124
+ 'select_statement.limit_clause.expr.literal.nbr.digit': 'limits',
125
+ } | common_contexts
126
+
127
+ if variant == 'p':
128
+ contexts_by_path = bash_contexts | contexts_by_path
129
+ elif variant == 'c':
130
+ contexts_by_path = {
131
+ 'export_table.path.identifier_ref': 'tables',
132
+ 'show_column_counts_command.path.identifier_ref': 'tables',
133
+ 'export_statement.export_tables.keyspace_name': 'keyspaces',
134
+
135
+ 'alter_tables_statement.properties.property.property_name': 'table-props',
136
+ 'alter_cql_table_statement.properties.property.property_name': 'table-props',
137
+ 'alter_tables_statement.properties.property.property_value.literal': 'table-props-value',
138
+ 'alter_cql_table_statement.properties.property.property_value.literal': 'table-props-value',
139
+
140
+ 'select_clause.projection.result_expr.expr.path.identifier_ref': 'columns',
141
+ 'export_statement.export_tables.export_table.column_name_list.column_name': 'columns',
142
+
143
+ 'consistency_statement.consistency': 'consistencies',
144
+ 'export_statement.export_to.export_database_type': 'export-database-types',
145
+ 'drop_export_database.export_database_name': 'export-databases',
146
+ 'use_export_db_statement.export_database_name': 'export-databases',
147
+ 'clean_up_export_session_statement.clean_up_export_sessions.export_session_name': 'export-sessions',
148
+ 'show_export_command.export_session_name': 'export-sessions',
149
+ 'import_statement.import_session.export_session_name': 'export-sessions-incomplete',
150
+ 'download_session_statement.export_session_name': 'export-sessions-incomplete',
151
+ } | bash_contexts | contexts_by_path
152
+ elif variant == 'l':
153
+ contexts_by_path = {
154
+ 'add_partition_action.partition_ref.partition_name': 'partition-columns',
155
+ 'show_topn_statement.topn_count': 'topn-counts',
156
+ 'show_topn_statement.topn_type': 'topn-types',
157
+ 'show_topn_statement.topn_window': 'topn-windows'
158
+ } | contexts_by_path
159
+ elif variant == 'x':
160
+ contexts_by_path = {
161
+ 'show_column_counts_command.path.identifier_ref': 'tables',
162
+ 'drop_export_database.export_database_name': 'export-databases',
163
+ 'use_export_db_statement.export_database_name': 'export-databases',
164
+ } | contexts_by_path
165
+
166
+ grammar = grammar.replace('select_clause: "SELECT"i hint_comment? projection', 'select_clause: ("SELECT"i | "XELECT"i) hint_comment? projection')
167
+
168
+ with offload():
169
+ with open('/tmp/grammar.lark', 'wt') as f:
170
+ f.write(grammar)
171
+
172
+ return LarkParser(grammar, contexts_by_path)
173
+
174
+ def get_completions(
175
+ self, document: Document, complete_event: CompleteEvent
176
+ ) -> Iterable[Completion]:
177
+ if not self.nested and self.options_lambda:
178
+ # for lazy completions
179
+ self.nested = NestedCompleter.from_nested_dict(self.options_lambda())
180
+
181
+ nested_words = set()
182
+
183
+ if self.nested:
184
+ # from NestedCompleter
185
+
186
+ # Split document.
187
+ text = document.text_before_cursor.lstrip()
188
+ stripped_len = len(document.text_before_cursor) - len(text)
189
+
190
+ # If there is a space, check for the first term, and use a
191
+ # subcompleter.
192
+ if " " in text:
193
+ first_term = text.split()[0]
194
+ completer = self.nested.options.get(first_term)
195
+
196
+ # If we have a sub completer, use this for the completions.
197
+ if completer is not None:
198
+ remaining_text = text[len(first_term) :].lstrip()
199
+ move_cursor = len(text) - len(remaining_text) + stripped_len
200
+
201
+ new_document = Document(
202
+ remaining_text,
203
+ cursor_position=document.cursor_position - move_cursor,
204
+ )
205
+
206
+ for c in completer.get_completions(new_document, complete_event):
207
+ nested_words.add(c.text)
208
+ yield c
209
+
210
+ # No space in the input: behave exactly like `WordCompleter`.
211
+ else:
212
+ completer = WordCompleter(
213
+ list(self.nested.options.keys()), ignore_case=self.nested.ignore_case
214
+ )
215
+ for c in completer.get_completions(document, complete_event):
216
+ nested_words.add(c.text)
217
+ yield c
218
+
219
+ if self.parser:
220
+ full = document.text_before_cursor
221
+ if self.dml:
222
+ full = self.dml + ' ' + full
223
+
224
+ words0 = []
225
+ words1 = []
226
+ context = {}
227
+ for word in self.parser.next_terminals(full, context=context):
228
+ if ex := self.expandable(word):
229
+ if ex in self.expandables:
230
+ e = self.expandables[ex]
231
+ if callable(e):
232
+ if self.auto_complete(ex) != 'off':
233
+ ctx = None
234
+ if 'last-id' in context:
235
+ ctx = context['last-id']
236
+ e = e(ctx)
237
+ words0.extend(e)
238
+ else:
239
+ words0.extend(e)
240
+ else:
241
+ words1.append(word)
242
+ words = words0 + words1
243
+
244
+ word_before_cursor = document.get_word_before_cursor(
245
+ WORD=self.WORD, pattern=self.pattern
246
+ )
247
+
248
+ word_before_cursor = word_before_cursor.lower()
249
+
250
+ def word_matches(word: str) -> bool:
251
+ return word.lower().startswith(word_before_cursor)
252
+
253
+ for word in words:
254
+ if word_matches(word) and word not in nested_words:
255
+ display = self.display_dict.get(word, word)
256
+ display_meta = self.meta_dict.get(word, "")
257
+ yield Completion(
258
+ word,
259
+ -len(word_before_cursor),
260
+ display=display,
261
+ display_meta=display_meta,
262
+ )
263
+
264
+ def completions_for_nesting(self, dml: str = None):
265
+ if dml:
266
+ return {dml: LarkCompleter(dml, expandables=self.expandables, variant=self.variant)}
267
+
268
+ return {
269
+ word.text.lower(): LarkCompleter(word.text, expandables=self.expandables, variant=self.variant)
270
+ for word in self.get_completions(Document(''), None)
271
+ }
272
+
273
+ def expandable(self, word: str):
274
+ return word.strip('`') if word.startswith('`') else None
275
+
276
+ def append_completions(self, key: str, value: dict[str, any]):
277
+ if isinstance(value, LarkCompleter) and self.variant == value.variant:
278
+ return
279
+
280
+ if self.nested:
281
+ self.nested = NestedCompleter.from_nested_dict(merge_completions(self.nested.options, value))
282
+ else:
283
+ self.nested = NestedCompleter.from_nested_dict(value)
284
+
285
+ def auto_complete(self, key: str, default = 'lazy'):
286
+ return Config().get(f'auto-complete.{self.variant}.{key}', default=default)