kaqing 2.0.172__py3-none-any.whl → 2.0.186__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 (140) hide show
  1. adam/app_session.py +2 -2
  2. adam/apps.py +18 -4
  3. adam/batch.py +1 -1
  4. adam/checks/check_utils.py +3 -1
  5. adam/commands/__init__.py +8 -2
  6. adam/commands/alter_tables.py +24 -35
  7. adam/commands/app/__init__.py +0 -0
  8. adam/commands/app/app.py +38 -0
  9. adam/commands/app/app_ping.py +38 -0
  10. adam/commands/app/show_app_actions.py +49 -0
  11. adam/commands/app/show_app_id.py +44 -0
  12. adam/commands/app/show_app_queues.py +38 -0
  13. adam/commands/app/utils_app.py +106 -0
  14. adam/commands/audit/audit.py +9 -27
  15. adam/commands/audit/audit_repair_tables.py +5 -7
  16. adam/commands/audit/audit_run.py +1 -1
  17. adam/commands/audit/completions_l.py +15 -0
  18. adam/commands/audit/show_last10.py +2 -14
  19. adam/commands/audit/show_slow10.py +2 -13
  20. adam/commands/audit/show_top10.py +2 -11
  21. adam/commands/audit/utils_show_top10.py +14 -1
  22. adam/commands/bash/bash.py +1 -1
  23. adam/commands/cat.py +5 -19
  24. adam/commands/cd.py +6 -8
  25. adam/commands/check.py +10 -18
  26. adam/commands/cli_commands.py +6 -1
  27. adam/commands/{cp.py → clipboard_copy.py} +34 -36
  28. adam/commands/code.py +2 -2
  29. adam/commands/command.py +94 -10
  30. adam/commands/commands_utils.py +19 -12
  31. adam/commands/cql/completions_c.py +28 -0
  32. adam/commands/cql/cqlsh.py +3 -7
  33. adam/commands/cql/utils_cql.py +22 -60
  34. adam/commands/deploy/deploy_pg_agent.py +2 -2
  35. adam/commands/deploy/undeploy_pg_agent.py +2 -2
  36. adam/commands/devices/device.py +39 -8
  37. adam/commands/devices/device_app.py +19 -29
  38. adam/commands/devices/device_auit_log.py +3 -3
  39. adam/commands/devices/device_cass.py +17 -23
  40. adam/commands/devices/device_export.py +12 -11
  41. adam/commands/devices/device_postgres.py +79 -63
  42. adam/commands/download_file.py +47 -0
  43. adam/commands/export/clean_up_all_export_sessions.py +3 -3
  44. adam/commands/export/clean_up_export_sessions.py +7 -19
  45. adam/commands/export/completions_x.py +11 -0
  46. adam/commands/export/download_export_session.py +40 -0
  47. adam/commands/export/drop_export_database.py +6 -22
  48. adam/commands/export/drop_export_databases.py +3 -9
  49. adam/commands/export/export.py +1 -17
  50. adam/commands/export/export_databases.py +93 -21
  51. adam/commands/export/export_select.py +8 -68
  52. adam/commands/export/export_sessions.py +209 -0
  53. adam/commands/export/export_use.py +13 -16
  54. adam/commands/export/export_x_select.py +48 -0
  55. adam/commands/export/exporter.py +108 -129
  56. adam/commands/export/import_files.py +44 -0
  57. adam/commands/export/import_session.py +10 -6
  58. adam/commands/export/importer.py +19 -5
  59. adam/commands/export/importer_athena.py +112 -41
  60. adam/commands/export/importer_sqlite.py +47 -19
  61. adam/commands/export/show_column_counts.py +11 -20
  62. adam/commands/export/show_export_databases.py +5 -2
  63. adam/commands/export/show_export_session.py +6 -15
  64. adam/commands/export/show_export_sessions.py +4 -11
  65. adam/commands/export/utils_export.py +46 -16
  66. adam/commands/find_files.py +51 -0
  67. adam/commands/find_processes.py +76 -0
  68. adam/commands/head.py +36 -0
  69. adam/commands/help.py +2 -2
  70. adam/commands/intermediate_command.py +6 -3
  71. adam/commands/ls.py +1 -1
  72. adam/commands/medusa/medusa_backup.py +13 -16
  73. adam/commands/medusa/medusa_restore.py +39 -32
  74. adam/commands/medusa/medusa_show_backupjobs.py +6 -4
  75. adam/commands/medusa/medusa_show_restorejobs.py +5 -3
  76. adam/commands/medusa/utils_medusa.py +15 -0
  77. adam/commands/nodetool.py +3 -8
  78. adam/commands/param_get.py +10 -12
  79. adam/commands/param_set.py +7 -10
  80. adam/commands/postgres/completions_p.py +22 -0
  81. adam/commands/postgres/postgres.py +25 -40
  82. adam/commands/postgres/postgres_databases.py +270 -0
  83. adam/commands/postgres/utils_postgres.py +33 -20
  84. adam/commands/preview_table.py +4 -2
  85. adam/commands/pwd.py +3 -3
  86. adam/commands/reaper/reaper_forward.py +2 -2
  87. adam/commands/reaper/reaper_run_abort.py +4 -10
  88. adam/commands/reaper/reaper_runs.py +3 -3
  89. adam/commands/reaper/reaper_schedule_activate.py +12 -12
  90. adam/commands/reaper/reaper_schedule_start.py +7 -12
  91. adam/commands/reaper/reaper_schedule_stop.py +7 -12
  92. adam/commands/reaper/utils_reaper.py +13 -6
  93. adam/commands/repair/repair_scan.py +0 -2
  94. adam/commands/repair/repair_stop.py +0 -1
  95. adam/commands/shell.py +7 -5
  96. adam/commands/show/show.py +1 -1
  97. adam/commands/show/show_adam.py +3 -3
  98. adam/commands/show/show_cassandra_repairs.py +5 -3
  99. adam/commands/show/show_cassandra_status.py +27 -20
  100. adam/commands/show/{show_commands.py → show_cli_commands.py} +2 -2
  101. adam/commands/show/show_login.py +2 -2
  102. adam/commands/show/show_params.py +2 -5
  103. adam/commands/show/show_processes.py +15 -14
  104. adam/commands/show/show_storage.py +9 -8
  105. adam/config.py +1 -0
  106. adam/embedded_params.py +1 -1
  107. adam/repl.py +20 -11
  108. adam/repl_commands.py +16 -9
  109. adam/repl_session.py +8 -1
  110. adam/repl_state.py +33 -10
  111. adam/sql/lark_completer.py +280 -0
  112. adam/sql/lark_parser.py +604 -0
  113. adam/sql/sql_state_machine.py +8 -2
  114. adam/utils.py +116 -29
  115. adam/utils_athena.py +7 -8
  116. adam/utils_issues.py +2 -2
  117. adam/utils_k8s/app_clusters.py +2 -2
  118. adam/utils_k8s/app_pods.py +5 -2
  119. adam/utils_k8s/cassandra_clusters.py +11 -3
  120. adam/utils_k8s/cassandra_nodes.py +2 -2
  121. adam/utils_k8s/k8s.py +14 -5
  122. adam/utils_k8s/kube_context.py +2 -2
  123. adam/utils_k8s/pods.py +23 -5
  124. adam/utils_k8s/statefulsets.py +5 -2
  125. adam/utils_local.py +4 -0
  126. adam/utils_repl/appendable_completer.py +6 -0
  127. adam/utils_repl/repl_completer.py +128 -2
  128. adam/utils_sqlite.py +14 -14
  129. adam/version.py +1 -1
  130. {kaqing-2.0.172.dist-info → kaqing-2.0.186.dist-info}/METADATA +1 -1
  131. kaqing-2.0.186.dist-info/RECORD +250 -0
  132. adam/commands/cql/cql_completions.py +0 -33
  133. adam/commands/export/export_handlers.py +0 -71
  134. adam/commands/export/export_select_x.py +0 -54
  135. adam/commands/postgres/postgres_context.py +0 -272
  136. adam/commands/postgres/psql_completions.py +0 -10
  137. kaqing-2.0.172.dist-info/RECORD +0 -230
  138. {kaqing-2.0.172.dist-info → kaqing-2.0.186.dist-info}/WHEEL +0 -0
  139. {kaqing-2.0.172.dist-info → kaqing-2.0.186.dist-info}/entry_points.txt +0 -0
  140. {kaqing-2.0.172.dist-info → kaqing-2.0.186.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,280 @@
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.lark_parser import LarkParser
9
+ from adam.utils import debug, log_timing, offload
10
+ from adam.utils_repl.appendable_completer import AppendableCompleter
11
+ from adam.utils_repl.repl_completer import merge_completions, preload
12
+
13
+ __all__ = [
14
+ "LarkCompleter",
15
+ ]
16
+
17
+ def default_columns(x: list[str]):
18
+ return 'id,x.,y.,z.'.split(',')
19
+
20
+ class LarkCompleter(Completer, AppendableCompleter):
21
+ SYSTEM = 'system'
22
+
23
+ def __init__(self,
24
+ dml: str = None,
25
+ expandables: dict = {},
26
+ variant: str = 'c',
27
+
28
+ name: str = None,
29
+ options_lambda: callable = None,
30
+ auto: str = 'lazy',
31
+ debug = False
32
+ ) -> None:
33
+ self.nested: NestedCompleter = None
34
+ self.options_lambda = options_lambda
35
+ if options_lambda and auto == 'lazy':
36
+ preload(options_lambda, log_key=name)
37
+
38
+ self.variant = variant
39
+ self.parser = None
40
+ self.dml = dml
41
+ self.expandables = expandables
42
+
43
+ self.display_dict = {}
44
+ self.meta_dict = {}
45
+ self.WORD = None
46
+ self.sentence = False
47
+ self.match_middle = False
48
+ self.pattern = None
49
+
50
+ self.debug = debug
51
+
52
+ if variant:
53
+ self.parser = LarkCompleter.lark_parser(variant)
54
+ self.preload_lazy_auto_completes()
55
+
56
+ def __repr__(self):
57
+ return f"LarkCompleter.{self.variant}"
58
+
59
+ def preload_lazy_auto_completes(self):
60
+ for key, value in self.expandables.items():
61
+ if callable(value):
62
+ if self.auto_complete(key) == 'lazy':
63
+ preload(value, log_key=key)
64
+
65
+ def from_lambda(name: str, options_lambda: callable, auto: str = 'lazy'):
66
+ return LarkCompleter(name=name, options_lambda=options_lambda, auto=auto, variant=None)
67
+
68
+ @functools.lru_cache()
69
+ def lark_parser(variant: str):
70
+ dir_path = os.path.dirname(os.path.realpath(__file__))
71
+ with open(dir_path + f"/qingl.lark") as f:
72
+ grammar: str = None
73
+ with log_timing(f'lark.{variant}.file-read'):
74
+ grammar = f.read()
75
+
76
+ common_contexts = {
77
+ 'cd_command.file_name': 'direct-dirs',
78
+ }
79
+
80
+ if variant in ['a', 'c0', 'p0', 'x0']:
81
+ grammar = grammar.replace('start: statement_sequence', f'start: qing_{variant}_statement')
82
+ contexts_by_path = {
83
+ } | common_contexts
84
+
85
+ debug(f'* GRAMMAR replaced to start: qing_{variant}_statement')
86
+
87
+ return LarkParser(grammar, contexts_by_path)
88
+ elif variant == 'system':
89
+ grammar = grammar.replace('start: statement_sequence', f'start: qing_{variant}_statement')
90
+ contexts_by_path = {
91
+ } | common_contexts
92
+
93
+ return LarkParser(grammar, contexts_by_path)
94
+
95
+ grammar = grammar.replace('qing_statement: qing_p_statement', f'qing_statement: qing_{variant}_statement')
96
+ debug(f'* GRAMMAR replaced to qing_statement: qing_{variant}_statement')
97
+
98
+ bash_contexts = {
99
+ 'bash_statement.host_name': 'hosts',
100
+ 'bash_statement.bash_command': 'bash-commands',
101
+ }
102
+
103
+ contexts_by_path = {
104
+ 'describe_keyspace.keyspace_name': 'keyspaces',
105
+ 'keyspace_ref.keyspace_path.namespace_ref.identifier_ref': 'tables',
106
+ 'preview_table_statement.path.identifier_ref': 'tables',
107
+
108
+ 'insert_statement.insert_select': 'column-names',
109
+ 'update_statement.set_clause.path.identifier_ref': 'column-names',
110
+ 'update_statement.where_clause.cond.expr.path.identifier_ref': 'column-names',
111
+ 'delete_statement.where_clause.cond.expr.path.identifier_ref': 'column-names',
112
+
113
+ 'select_clause.projection.result_expr.expr.path.identifier_ref': 'columns',
114
+ 'select_from.where_clause.cond.expr.path.identifier_ref': 'columns',
115
+ 'select_from.where_clause.cond.expr.logical_term.and_expr.cond.expr.path.identifier_ref': 'columns',
116
+ 'select_from.group_by_clause.group_term.expr.path.identifier_ref': 'columns',
117
+ 'select_statement.order_by_clause.ordering_term.expr.path.identifier_ref': 'columns',
118
+ 'select_from.from_clause.from_terms.join_clause.ansi_join_clause.ansi_join_predicate.expr.path.identifier_ref': 'columns',
119
+ 'select_from.from_clause.from_terms.join_clause.ansi_join_clause.ansi_join_predicate.expr.comparison_term.relational_expr.expr.path.identifier_ref': 'columns',
120
+
121
+ 'select_from.from_clause.from_terms.from_generic.alias.identifier_ref': 'column-aliases',
122
+
123
+ 'select_statement.limit_clause.expr.literal.nbr.digit': 'limits',
124
+ } | common_contexts
125
+
126
+ if variant == 'p':
127
+ contexts_by_path = bash_contexts | contexts_by_path
128
+ elif variant == 'c':
129
+ contexts_by_path = {
130
+ 'export_table.path.identifier_ref': 'tables',
131
+ 'show_column_counts_command.path.identifier_ref': 'tables',
132
+ 'export_statement.export_tables.keyspace_name': 'keyspaces',
133
+
134
+ 'alter_cql_table_statement.properties.property.property_name': 'table-props',
135
+ 'alter_tables_statement.properties.property.property_name': 'table-props',
136
+ 'alter_cql_table_statement.properties.property.property_value.literal': 'table-props-value',
137
+
138
+ 'select_clause.projection.result_expr.expr.path.identifier_ref': 'columns',
139
+ 'export_statement.export_tables.export_table.column_name_list.column_name': 'columns',
140
+
141
+ 'consistency_statement.consistency': 'consistencies',
142
+ 'export_statement.export_to.export_database_type': 'export-database-types',
143
+ 'drop_export_database.export_database_name': 'export-databases',
144
+ 'use_export_db_statement.export_database_name': 'export-databases',
145
+ 'clean_up_export_session_statement.clean_up_export_sessions.export_session_name': 'export-sessions',
146
+ 'show_export_command.export_session_name': 'export-sessions',
147
+ 'import_statement.import_session.export_session_name': 'export-sessions-incomplete',
148
+ 'download_session_statement.export_session_name': 'export-sessions-incomplete',
149
+ } | bash_contexts | contexts_by_path
150
+ elif variant == 'l':
151
+ contexts_by_path = {
152
+ 'add_partition_action.partition_ref.partition_name': 'partition-columns',
153
+ 'show_topn_statement.topn_count': 'topn-counts',
154
+ 'show_topn_statement.topn_type': 'topn-types',
155
+ 'show_topn_statement.topn_window': 'topn-windows'
156
+ } | contexts_by_path
157
+ elif variant == 'x':
158
+ contexts_by_path = {
159
+ 'show_column_counts_command.path.identifier_ref': 'tables',
160
+ 'drop_export_database.export_database_name': 'export-databases',
161
+ 'use_export_db_statement.export_database_name': 'export-databases',
162
+ } | contexts_by_path
163
+
164
+ grammar = grammar.replace('select_clause: "SELECT"i hint_comment? projection', 'select_clause: ("SELECT"i | "XELECT"i) hint_comment? projection')
165
+
166
+ with offload():
167
+ with open('/tmp/grammar.lark', 'wt') as f:
168
+ f.write(grammar)
169
+
170
+ return LarkParser(grammar, contexts_by_path)
171
+
172
+ def get_completions(
173
+ self, document: Document, complete_event: CompleteEvent
174
+ ) -> Iterable[Completion]:
175
+ if not self.nested and self.options_lambda:
176
+ # for lazy completions
177
+ self.nested = NestedCompleter.from_nested_dict(self.options_lambda())
178
+
179
+ if self.nested:
180
+ # from NestedCompleter
181
+
182
+ # Split document.
183
+ text = document.text_before_cursor.lstrip()
184
+ stripped_len = len(document.text_before_cursor) - len(text)
185
+
186
+ # If there is a space, check for the first term, and use a
187
+ # subcompleter.
188
+ if " " in text:
189
+ first_term = text.split()[0]
190
+ completer = self.nested.options.get(first_term)
191
+
192
+ # If we have a sub completer, use this for the completions.
193
+ if completer is not None:
194
+ remaining_text = text[len(first_term) :].lstrip()
195
+ move_cursor = len(text) - len(remaining_text) + stripped_len
196
+
197
+ new_document = Document(
198
+ remaining_text,
199
+ cursor_position=document.cursor_position - move_cursor,
200
+ )
201
+
202
+ for c in completer.get_completions(new_document, complete_event):
203
+ yield c
204
+
205
+ # No space in the input: behave exactly like `WordCompleter`.
206
+ else:
207
+ completer = WordCompleter(
208
+ list(self.nested.options.keys()), ignore_case=self.nested.ignore_case
209
+ )
210
+ for c in completer.get_completions(document, complete_event):
211
+ yield c
212
+
213
+ if self.parser:
214
+ full = document.text_before_cursor
215
+ if self.dml:
216
+ full = self.dml + ' ' + full
217
+
218
+ words0 = []
219
+ words1 = []
220
+ context = {}
221
+ for word in self.parser.next_terminals(full, context=context):
222
+ if ex := self.expandable(word):
223
+ if ex in self.expandables:
224
+ e = self.expandables[ex]
225
+ if callable(e):
226
+ if self.auto_complete(ex) != 'off':
227
+ ctx = None
228
+ if 'last-id' in context:
229
+ ctx = context['last-id']
230
+ e = e(ctx)
231
+ words0.extend(e)
232
+ else:
233
+ words0.extend(e)
234
+ else:
235
+ words1.append(word)
236
+ words = words0 + words1
237
+
238
+ word_before_cursor = document.get_word_before_cursor(
239
+ WORD=self.WORD, pattern=self.pattern
240
+ )
241
+
242
+ word_before_cursor = word_before_cursor.lower()
243
+
244
+ def word_matches(word: str) -> bool:
245
+ return word.lower().startswith(word_before_cursor)
246
+
247
+ for a in words:
248
+ if word_matches(a):
249
+ display = self.display_dict.get(a, a)
250
+ display_meta = self.meta_dict.get(a, "")
251
+ yield Completion(
252
+ a,
253
+ -len(word_before_cursor),
254
+ display=display,
255
+ display_meta=display_meta,
256
+ )
257
+
258
+ def completions_for_nesting(self, dml: str = None):
259
+ if dml:
260
+ return {dml: LarkCompleter(dml, expandables=self.expandables, variant=self.variant)}
261
+
262
+ return {
263
+ word.text.lower(): LarkCompleter(word.text, expandables=self.expandables, variant=self.variant)
264
+ for word in self.get_completions(Document(''), None)
265
+ }
266
+
267
+ def expandable(self, word: str):
268
+ return word.strip('`') if word.startswith('`') else None
269
+
270
+ def append_completions(self, key: str, value: dict[str, any]):
271
+ if isinstance(value, LarkCompleter) and self.variant == value.variant:
272
+ return
273
+
274
+ if self.nested:
275
+ self.nested = NestedCompleter.from_nested_dict(merge_completions(self.nested.options, value))
276
+ else:
277
+ self.nested = NestedCompleter.from_nested_dict(value)
278
+
279
+ def auto_complete(self, key: str, default = 'lazy'):
280
+ return Config().get(f'auto-complete.{self.variant}.{key}', default=default)